├── src
├── tcp.md
├── .editorconfig
├── IpcServiceFramework.snk
├── JKang.IpcServiceFramework.Core.Tests
│ ├── Fixtures
│ │ ├── EnumType.cs
│ │ ├── IComplexType.cs
│ │ └── ComplexType.cs
│ ├── JKang.IpcServiceFramework.Core.Tests.csproj
│ └── DefaultValueConverterTest.cs
├── JKang.IpcServiceFramework.NamedPipeTests
│ ├── Fixtures
│ │ ├── ITestDto.cs
│ │ ├── ITestService2.cs
│ │ ├── TestDto.cs
│ │ ├── UnserializableObject.cs
│ │ ├── ITestService.cs
│ │ └── XorStream.cs
│ ├── JKang.IpcServiceFramework.NamedPipeTests.csproj
│ ├── StreamTranslatorTest.cs
│ ├── MultipleEndpointTest.cs
│ ├── EdgeCaseTest.cs
│ ├── SimpleTypeNameContractTest.cs
│ ├── ErrorTest.cs
│ └── ContractTest.cs
├── JKang.IpcServiceFramework.TcpTests
│ ├── Fixtures
│ │ └── ITestService.cs
│ ├── JKang.IpcServiceFramework.TcpTests.csproj
│ ├── HappyPathTest.cs
│ └── EdgeCaseTest.cs
├── JKang.IpcServiceFramework.Client.NamedPipe
│ ├── NamedPipeIpcClientOptions.cs
│ ├── JKang.IpcServiceFramework.Client.NamedPipe.csproj
│ ├── NamedPipeIpcClient.cs
│ └── NamedPipeIpcClientServiceCollectionExtensions.cs
├── JKang.IpcServiceFramework.Core
│ ├── IpcStatus.cs
│ ├── Services
│ │ ├── IValueConverter.cs
│ │ ├── IIpcMessageSerializer.cs
│ │ ├── DefaultIpcMessageSerializer.cs
│ │ └── DefaultValueConverter.cs
│ ├── IpcException.cs
│ ├── GlobalSuppressions.cs
│ ├── IpcCommunicationException.cs
│ ├── IpcSerializationException.cs
│ ├── JKang.IpcServiceFramework.Core.csproj
│ ├── IpcFaultException.cs
│ ├── IpcRequest.cs
│ ├── IpcResponse.cs
│ └── IO
│ │ ├── IpcWriter.cs
│ │ └── IpcReader.cs
├── JKang.IpcServiceFramework.Client
│ ├── IIpcClientFactory.cs
│ ├── JKang.IpcServiceFramework.Client.csproj
│ ├── IpcClientServiceCollectionExtensions.cs
│ ├── IIpcClient.cs
│ ├── IpcStreamWrapper.cs
│ ├── IpcClientOptions.cs
│ ├── IpcClientRegistration.cs
│ ├── IpcClientFactory.cs
│ └── IpcClient.cs
├── JKang.IpcServiceFramework.Hosting.NamedPipe
│ ├── NamedPipeIpcEndpointOptions.cs
│ ├── GlobalSuppressions.cs
│ ├── JKang.IpcServiceFramework.Hosting.NamedPipe.csproj
│ ├── NamedPipeIpcHostBuilderExtensions.cs
│ ├── NamedPipeIpcEndpoint.cs
│ └── NamedPipeNative.cs
├── JKang.IpcServiceFramework.Hosting
│ ├── IIpcHostBuilder.cs
│ ├── IIpcEndpoint.cs
│ ├── GlobalSuppressions.cs
│ ├── GenericHostBuilderExtensions.cs
│ ├── IpcHostingConfigurationException.cs
│ ├── JKang.IpcServiceFramework.Hosting.csproj
│ ├── IpcEndpointOptions.cs
│ ├── IpcHostBuilder.cs
│ ├── IpcBackgroundService.cs
│ └── IpcEndpoint.cs
├── JKang.IpcServiceFramework.Client.Tcp
│ ├── JKang.IpcServiceFramework.Client.Tcp.csproj
│ ├── TcpIpcClientOptions.cs
│ ├── TcpIpcClientServiceCollectionExtensions.cs
│ └── TcpIpcClient.cs
├── JKang.IpcServiceFramework.Hosting.Tcp
│ ├── JKang.IpcServiceFramework.Hosting.Tcp.csproj
│ ├── GlobalSuppressions.cs
│ ├── TcpIpcEndpointOptions.cs
│ ├── TcpIpcHostBuilderExtensions.cs
│ └── TcpIpcEndpoint.cs
├── JKang.IpcServiceFramework.Testing
│ ├── JKang.IpcServiceFramework.Testing.csproj
│ ├── IpcApplicationFactory.cs
│ └── TestHelpers.cs
├── Directory.Build.props
└── IpcServiceFramework.sln
├── global.json
├── samples
├── IpcServiceSample.ServiceContracts
│ ├── IInterProcessService.cs
│ └── IpcServiceSample.ServiceContracts.csproj
├── IpcServiceSample.Server
│ ├── InterProcessService.cs
│ ├── IpcServiceSample.Server.csproj
│ └── Program.cs
├── IpcServiceSample.Client
│ ├── IpcServiceSample.ConsoleClient.csproj
│ └── Program.cs
└── IpcServiceSample.sln
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── FUNDING.yml
└── copilot-instructions.md
├── doc
├── stream-translator.md
└── tcp
│ └── security.md
├── LICENSE
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── README.md
└── .gitignore
/src/tcp.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 | indent_style = space
3 | indent_size = 4
4 | insert_final_newline = true
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "10.0.101",
4 | "rollForward": "latestFeature"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/IpcServiceFramework.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacqueskang/IpcServiceFramework/HEAD/src/IpcServiceFramework.snk
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core.Tests/Fixtures/EnumType.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.Core.Tests.Fixtures
2 | {
3 | public enum EnumType
4 | {
5 | FirstOption,
6 | SecondOption
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.NamedPipeTests/Fixtures/ITestDto.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.NamedPipeTests.Fixtures
2 | {
3 | public interface ITestDto
4 | {
5 | string Value { get; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.NamedPipeTests/Fixtures/ITestService2.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.NamedPipeTests.Fixtures
2 | {
3 | public interface ITestService2
4 | {
5 | int SomeMethod();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.TcpTests/Fixtures/ITestService.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.TcpTests.Fixtures
2 | {
3 | public interface ITestService
4 | {
5 | string StringType(string input);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/samples/IpcServiceSample.ServiceContracts/IInterProcessService.cs:
--------------------------------------------------------------------------------
1 | namespace IpcServiceSample.ServiceContracts
2 | {
3 | public interface IInterProcessService
4 | {
5 | string ReverseString(string input);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/samples/IpcServiceSample.ServiceContracts/IpcServiceSample.ServiceContracts.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.NamedPipeTests/Fixtures/TestDto.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.NamedPipeTests.Fixtures
2 | {
3 | public class TestDto : ITestDto
4 | {
5 | public string Value { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core.Tests/Fixtures/IComplexType.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.Core.Tests.Fixtures
2 | {
3 | public interface IComplexType
4 | {
5 | int Int32Value { get; }
6 | string StringValue { get; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client.NamedPipe/NamedPipeIpcClientOptions.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.Client.NamedPipe
2 | {
3 | public class NamedPipeIpcClientOptions : IpcClientOptions
4 | {
5 | public string PipeName { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/IpcStatus.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework
2 | {
3 | public enum IpcStatus: int
4 | {
5 | Unknown = 0,
6 | Ok = 200,
7 | BadRequest = 400,
8 | InternalServerError = 500,
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client/IIpcClientFactory.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.Client
2 | {
3 | public interface IIpcClientFactory
4 | where TContract: class
5 | {
6 | IIpcClient CreateClient(string name);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting.NamedPipe/NamedPipeIpcEndpointOptions.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.Hosting.NamedPipe
2 | {
3 | public class NamedPipeIpcEndpointOptions : IpcEndpointOptions
4 | {
5 | public string PipeName { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/Services/IValueConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace JKang.IpcServiceFramework.Services
4 | {
5 | public interface IValueConverter
6 | {
7 | bool TryConvert(object origValue, Type destType, out object destValue);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting/IIpcHostBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace JKang.IpcServiceFramework.Hosting
4 | {
5 | public interface IIpcHostBuilder
6 | {
7 | IIpcHostBuilder AddIpcEndpoint(Func factory);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core.Tests/Fixtures/ComplexType.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.Core.Tests.Fixtures
2 | {
3 | public class ComplexType : IComplexType
4 | {
5 | public int Int32Value { get; set; }
6 | public string StringValue { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting/IIpcEndpoint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 |
5 | namespace JKang.IpcServiceFramework.Hosting
6 | {
7 | public interface IIpcEndpoint: IDisposable
8 | {
9 | Task ExecuteAsync(CancellationToken stoppingToken);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/samples/IpcServiceSample.Server/InterProcessService.cs:
--------------------------------------------------------------------------------
1 | using IpcServiceSample.ServiceContracts;
2 | using System;
3 |
4 | namespace IpcServiceSample.Server
5 | {
6 | public class InterProcessService : IInterProcessService
7 | {
8 | public string ReverseString(string input)
9 | {
10 | char[] charArray = input.ToCharArray();
11 | Array.Reverse(charArray);
12 | return new string(charArray);
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client.Tcp/JKang.IpcServiceFramework.Client.Tcp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | ipc,interprocess,communication,wcf,client,tcp
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.NamedPipeTests/Fixtures/UnserializableObject.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 |
3 | namespace JKang.IpcServiceFramework.NamedPipeTests.Fixtures
4 | {
5 | public class UnserializableObject : IPAddress
6 | {
7 | public static UnserializableObject Create()
8 | => new UnserializableObject(Loopback.GetAddressBytes());
9 |
10 | private UnserializableObject(byte[] address)
11 | : base(address)
12 | { }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting.Tcp/JKang.IpcServiceFramework.Hosting.Tcp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | ipc,interprocess,communication,wcf,hosting,tcp
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/IpcException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace JKang.IpcServiceFramework
4 | {
5 | public abstract class IpcException : Exception
6 | {
7 | protected IpcException()
8 | { }
9 |
10 | protected IpcException(string message)
11 | : base(message)
12 | { }
13 |
14 | protected IpcException(string message, Exception innerException)
15 | : base(message, innerException)
16 | { }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client.NamedPipe/JKang.IpcServiceFramework.Client.NamedPipe.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | ipc,interprocess,communication,wcf,client,namedpipe
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project.
3 | // Project-level suppressions either have no target or are given
4 | // a specific target and scoped to a namespace, type, member, etc.
5 |
6 | using System.Diagnostics.CodeAnalysis;
7 |
8 | [assembly: SuppressMessage("Globalization",
9 | "CA1303:Do not pass literals as localized parameters",
10 | Justification = "")]
11 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project.
3 | // Project-level suppressions either have no target or are given
4 | // a specific target and scoped to a namespace, type, member, etc.
5 |
6 | using System.Diagnostics.CodeAnalysis;
7 |
8 | [assembly: SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "Globalization support is not planned.")]
9 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting.Tcp/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project.
3 | // Project-level suppressions either have no target or are given
4 | // a specific target and scoped to a namespace, type, member, etc.
5 |
6 | using System.Diagnostics.CodeAnalysis;
7 |
8 | [assembly: SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "Globalization support is not planned.")]
9 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting.Tcp/TcpIpcEndpointOptions.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Security.Cryptography.X509Certificates;
3 |
4 | namespace JKang.IpcServiceFramework.Hosting.Tcp
5 | {
6 | public class TcpIpcEndpointOptions : IpcEndpointOptions
7 | {
8 | public IPAddress IpEndpoint { get; set; } = IPAddress.Loopback;
9 | public int Port { get; set; }
10 | public bool EnableSsl { get; set; }
11 | public X509Certificate SslCertificate { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting.NamedPipe/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project.
3 | // Project-level suppressions either have no target or are given
4 | // a specific target and scoped to a namespace, type, member, etc.
5 |
6 | using System.Diagnostics.CodeAnalysis;
7 |
8 | [assembly: SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "Globalization support is not planned.")]
9 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/IpcCommunicationException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace JKang.IpcServiceFramework
4 | {
5 | public class IpcCommunicationException : IpcException
6 | {
7 | public IpcCommunicationException()
8 | { }
9 |
10 | public IpcCommunicationException(string message)
11 | : base(message)
12 | { }
13 |
14 | public IpcCommunicationException(string message, Exception innerException)
15 | : base(message, innerException)
16 | { }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/IpcSerializationException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace JKang.IpcServiceFramework
4 | {
5 | public class IpcSerializationException : IpcException
6 | {
7 | public IpcSerializationException()
8 | { }
9 |
10 | public IpcSerializationException(string message)
11 | : base(message)
12 | { }
13 |
14 | public IpcSerializationException(string message, Exception innerException)
15 | : base(message, innerException)
16 | { }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting/GenericHostBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using JKang.IpcServiceFramework.Hosting;
2 | using System;
3 |
4 | namespace Microsoft.Extensions.Hosting
5 | {
6 | public static class GenericHostBuilderExtensions
7 | {
8 | public static IHostBuilder ConfigureIpcHost(this IHostBuilder builder, Action configure)
9 | {
10 | var ipcHostBuilder = new IpcHostBuilder(builder);
11 | configure?.Invoke(ipcHostBuilder);
12 | return builder;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client.Tcp/TcpIpcClientOptions.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Net.Security;
3 |
4 | namespace JKang.IpcServiceFramework.Client.Tcp
5 | {
6 | public class TcpIpcClientOptions : IpcClientOptions
7 | {
8 | public IPAddress ServerIp { get; set; } = IPAddress.Loopback;
9 | public int ServerPort { get; set; } = 11843;
10 | public bool EnableSsl { get; set; }
11 | public string SslServerIdentity { get; set; }
12 | public RemoteCertificateValidationCallback SslValidationCallback { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/JKang.IpcServiceFramework.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | JKang.IpcServiceFramework
6 | ipc,interprocess,communication,wcf
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting/IpcHostingConfigurationException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace JKang.IpcServiceFramework.Hosting
4 | {
5 | public class IpcHostingConfigurationException : Exception
6 | {
7 | public IpcHostingConfigurationException()
8 | { }
9 |
10 | public IpcHostingConfigurationException(string message)
11 | : base(message)
12 | { }
13 |
14 | public IpcHostingConfigurationException(string message, Exception innerException)
15 | : base(message, innerException)
16 | { }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting/JKang.IpcServiceFramework.Hosting.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | ipc,interprocess,communication,wcf,hosting
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Additional context**
24 | Add any other context about the problem here.
25 |
--------------------------------------------------------------------------------
/samples/IpcServiceSample.Server/IpcServiceSample.Server.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client/JKang.IpcServiceFramework.Client.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | ipc,interprocess,communication,wcf,client
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/samples/IpcServiceSample.Client/IpcServiceSample.ConsoleClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting/IpcEndpointOptions.cs:
--------------------------------------------------------------------------------
1 | using JKang.IpcServiceFramework.Services;
2 | using System;
3 | using System.IO;
4 |
5 | namespace JKang.IpcServiceFramework.Hosting
6 | {
7 | public class IpcEndpointOptions
8 | {
9 | public int MaxConcurrentCalls { get; set; } = 4;
10 |
11 | public bool IncludeFailureDetailsInResponse { get; set; }
12 |
13 | public Func StreamTranslator { get; set; }
14 |
15 | public IIpcMessageSerializer Serializer { get; set; } = new DefaultIpcMessageSerializer();
16 |
17 | public IValueConverter ValueConverter { get; set; } = new DefaultValueConverter();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: jacqueskang
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/Services/IIpcMessageSerializer.cs:
--------------------------------------------------------------------------------
1 | namespace JKang.IpcServiceFramework.Services
2 | {
3 | public interface IIpcMessageSerializer
4 | {
5 | ///
6 | byte[] SerializeRequest(IpcRequest request);
7 |
8 | ///
9 | IpcResponse DeserializeResponse(byte[] binary);
10 |
11 | ///
12 | IpcRequest DeserializeRequest(byte[] binary);
13 |
14 | ///
15 | byte[] SerializeResponse(IpcResponse response);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting.NamedPipe/JKang.IpcServiceFramework.Hosting.NamedPipe.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | ipc,interprocess,communication,wcf,hosting,namedpipe
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Testing/JKang.IpcServiceFramework.Testing.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/doc/stream-translator.md:
--------------------------------------------------------------------------------
1 | ## Stream translators
2 |
3 | If you want to process the binary data after serialisation or before deserialisation, for example to add a custom handshake when the connection begins, you can do so using a stream translator. Host and client classes allow you to pass a `Func` stream translation callback in their constructors, which can be used to "wrap" a custom stream around the network stream. This is supported on TCP communications both with and without SSL enabled. See the `XorStream` class in the IpcServiceSample.ServiceContracts project for an example of a stream translator.
4 |
5 | Stream translators are also useful for logging packets for debugging. See the `LoggingStream` class in the IpcServiceSample.ServiceContracts project for an example of using a stream translator to log traffic.
6 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Jacques Kang and other GitHub contributors
5 |
6 | https://github.com/jacqueskang/IpcServiceFramework/blob/develop/LICENSE
7 | https://github.com/jacqueskang/IpcServiceFramework
8 | https://github.com/jacqueskang/IpcServiceFramework
9 | 3.0.0
10 | true
11 | ..\IpcServiceFramework.snk
12 |
13 |
14 |
15 | DISABLE_DYNAMIC_CODE_GENERATION
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/IpcFaultException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace JKang.IpcServiceFramework
4 | {
5 | ///
6 | /// An exception that can be transfered from server to client
7 | ///
8 | public class IpcFaultException : IpcException
9 | {
10 | public IpcFaultException(IpcStatus status)
11 | {
12 | Status = status;
13 | }
14 |
15 | public IpcFaultException(IpcStatus status, string message)
16 | : base(message)
17 | {
18 | Status = status;
19 | }
20 |
21 | public IpcFaultException(IpcStatus status, string message, Exception innerException)
22 | : base(message, innerException)
23 | {
24 | Status = status;
25 | }
26 |
27 | public IpcStatus Status { get; }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client/IpcClientServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using JKang.IpcServiceFramework.Client;
2 | using Microsoft.Extensions.DependencyInjection.Extensions;
3 |
4 | namespace Microsoft.Extensions.DependencyInjection
5 | {
6 | public static class IpcClientServiceCollectionExtensions
7 | {
8 | public static IServiceCollection AddIpcClient(
9 | this IServiceCollection services,
10 | IpcClientRegistration registration)
11 | where TContract : class
12 | where TIpcClientOptions : IpcClientOptions
13 | {
14 | services
15 | .TryAddScoped, IpcClientFactory>();
16 |
17 | services.AddSingleton(registration);
18 |
19 | return services;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client.NamedPipe/NamedPipeIpcClient.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.IO.Pipes;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace JKang.IpcServiceFramework.Client.NamedPipe
7 | {
8 | internal class NamedPipeIpcClient : IpcClient
9 | where TInterface : class
10 | {
11 | private readonly NamedPipeIpcClientOptions _options;
12 |
13 | public NamedPipeIpcClient(
14 | string name,
15 | NamedPipeIpcClientOptions options)
16 | : base(name, options)
17 | {
18 | _options = options;
19 | }
20 |
21 | protected override async Task ConnectToServerAsync(CancellationToken cancellationToken)
22 | {
23 | var stream = new NamedPipeClientStream(".", _options.PipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
24 | await stream.ConnectAsync(_options.ConnectionTimeout, cancellationToken).ConfigureAwait(false);
25 | return new IpcStreamWrapper(stream);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Jacques Kang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.NamedPipeTests/Fixtures/ITestService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Net;
5 | using System.Numerics;
6 | using System.Threading.Tasks;
7 |
8 | namespace JKang.IpcServiceFramework.NamedPipeTests.Fixtures
9 | {
10 | public interface ITestService
11 | {
12 | int PrimitiveTypes(bool a, byte b, sbyte c, char d, decimal e, double f, float g, int h, uint i, long j,
13 | ulong k, short l, ushort m);
14 | string StringType(string input);
15 | Complex ComplexType(Complex input);
16 | IEnumerable ComplexTypeArray(IEnumerable input);
17 | void ReturnVoid();
18 | DateTime DateTime(DateTime input);
19 | DateTimeStyles EnumType(DateTimeStyles input);
20 | byte[] ByteArray(byte[] input);
21 | T GenericMethod(T input);
22 | Task AsyncMethod();
23 | void ThrowException();
24 | ITestDto Abstraction(ITestDto input);
25 | void UnserializableInput(UnserializableObject input);
26 | UnserializableObject UnserializableOutput();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/samples/IpcServiceSample.Server/Program.cs:
--------------------------------------------------------------------------------
1 | using IpcServiceSample.Server;
2 | using IpcServiceSample.ServiceContracts;
3 | using JKang.IpcServiceFramework.Hosting;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Hosting;
6 | using Microsoft.Extensions.Logging;
7 |
8 | namespace IpcServiceSample.ConsoleServer
9 | {
10 | class Program
11 | {
12 | public static void Main(string[] args)
13 | {
14 | CreateHostBuilder(args).Build().Run();
15 | }
16 |
17 | public static IHostBuilder CreateHostBuilder(string[] args) =>
18 | Host.CreateDefaultBuilder(args)
19 | .ConfigureServices(services =>
20 | {
21 | services.AddScoped();
22 | })
23 | .ConfigureIpcHost(builder =>
24 | {
25 | builder.AddNamedPipeEndpoint("pipeinternal");
26 | })
27 | .ConfigureLogging(builder =>
28 | {
29 | builder.SetMinimumLevel(LogLevel.Debug);
30 | });
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core.Tests/JKang.IpcServiceFramework.Core.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net10.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 | all
13 | runtime; build; native; contentfiles; analyzers; buildtransitive
14 |
15 |
16 |
17 |
18 | all
19 | runtime; build; native; contentfiles; analyzers; buildtransitive
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting/IpcHostBuilder.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Hosting;
3 | using System;
4 |
5 | namespace JKang.IpcServiceFramework.Hosting
6 | {
7 | internal class IpcHostBuilder : IIpcHostBuilder
8 | {
9 | private readonly IHostBuilder _hostBuilder;
10 |
11 | public IpcHostBuilder(IHostBuilder hostBuilder)
12 | {
13 | _hostBuilder = hostBuilder ?? throw new ArgumentNullException(nameof(hostBuilder));
14 |
15 | _hostBuilder.ConfigureServices((_, services) =>
16 | {
17 | services
18 | .AddHostedService();
19 | });
20 | }
21 |
22 | public IIpcHostBuilder AddIpcEndpoint(Func endpointFactory)
23 | {
24 | if (endpointFactory is null)
25 | {
26 | throw new ArgumentNullException(nameof(endpointFactory));
27 | }
28 |
29 | _hostBuilder.ConfigureServices((_, services) =>
30 | {
31 | services.AddSingleton(endpointFactory);
32 | });
33 |
34 | return this;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.NamedPipeTests/JKang.IpcServiceFramework.NamedPipeTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net10.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | runtime; build; native; contentfiles; analyzers; buildtransitive
15 | all
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client.NamedPipe/NamedPipeIpcClientServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using JKang.IpcServiceFramework.Client;
2 | using JKang.IpcServiceFramework.Client.NamedPipe;
3 | using System;
4 |
5 | namespace Microsoft.Extensions.DependencyInjection
6 | {
7 | public static class NamedPipeIpcClientServiceCollectionExtensions
8 | {
9 | public static IServiceCollection AddNamedPipeIpcClient(
10 | this IServiceCollection services, string name, string pipeName)
11 | where TContract : class
12 | {
13 | return services.AddNamedPipeIpcClient(name, (_, options) =>
14 | {
15 | options.PipeName = pipeName;
16 | });
17 | }
18 |
19 | public static IServiceCollection AddNamedPipeIpcClient(
20 | this IServiceCollection services, string name,
21 | Action configureOptions)
22 | where TContract : class
23 | {
24 | services.AddIpcClient(new IpcClientRegistration(name,
25 | (_, options) => new NamedPipeIpcClient(name, options), configureOptions));
26 |
27 | return services;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client.Tcp/TcpIpcClientServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using JKang.IpcServiceFramework.Client;
2 | using JKang.IpcServiceFramework.Client.Tcp;
3 | using System;
4 | using System.Net;
5 |
6 | namespace Microsoft.Extensions.DependencyInjection
7 | {
8 | public static class TcpIpcClientServiceCollectionExtensions
9 | {
10 | public static IServiceCollection AddTcpIpcClient(
11 | this IServiceCollection services, string name, IPAddress serverIp, int serverPort)
12 | where TContract : class
13 | {
14 | return services.AddTcpIpcClient(name, (_, options) =>
15 | {
16 | options.ServerIp = serverIp;
17 | options.ServerPort = serverPort;
18 | });
19 | }
20 |
21 | public static IServiceCollection AddTcpIpcClient(
22 | this IServiceCollection services, string name,
23 | Action configureOptions)
24 | where TContract : class
25 | {
26 | services.AddIpcClient(new IpcClientRegistration(name,
27 | (_, options) => new TcpIpcClient(name, options), configureOptions));
28 |
29 | return services;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client/IIpcClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq.Expressions;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace JKang.IpcServiceFramework.Client
7 | {
8 | public interface IIpcClient
9 | where TInterface : class
10 | {
11 | string Name { get; }
12 |
13 | #if !DISABLE_DYNAMIC_CODE_GENERATION
14 | Task InvokeAsync(
15 | Expression> exp,
16 | CancellationToken cancellationToken = default);
17 |
18 | Task InvokeAsync(
19 | Expression> exp,
20 | CancellationToken cancellationToken = default);
21 |
22 | Task InvokeAsync(
23 | Expression> exp,
24 | CancellationToken cancellationToken = default);
25 |
26 | Task InvokeAsync(
27 | Expression>> exp,
28 | CancellationToken cancellationToken = default);
29 | #endif
30 |
31 | Task InvokeAsync(IpcRequest request,
32 | CancellationToken cancellationToken = default(CancellationToken));
33 |
34 | Task InvokeAsync(IpcRequest request,
35 | CancellationToken cancellationToken = default(CancellationToken));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.TcpTests/JKang.IpcServiceFramework.TcpTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net10.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | runtime; build; native; contentfiles; analyzers; buildtransitive
15 | all
16 |
17 |
18 | runtime; build; native; contentfiles; analyzers; buildtransitive
19 | all
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | #Contributing
2 |
3 | ## Git workflow
4 |
5 | Follow [Gitflow](https://datasift.github.io/gitflow/IntroducingGitFlow.html).
6 |
7 | *Notes:*
8 | - Use **Rebase and merge** to complete PR merging to develop branch too have a clean and linear history.
9 | - Use **Create a merge commit** to complete PR merging to master branch so that "first-parent" commits matches the versioning history.
10 |
11 | ## Commit syntax
12 |
13 | Follow [Conventional Commits 1.0](https://www.conventionalcommits.org/en/v1.0.0/)
14 |
15 | ## Versioning
16 |
17 | Follow [Semantic Versioning 2.0](https://semver.org/).
18 |
19 | Currently all JKang.IpcServiceFramework.* packages share a same version fixed in [version.yml](/build/version.yml). You should thus update this file when starting working on a new milestone.
20 |
21 | ## CI/CD
22 |
23 | - A PR build is triggered when any PR is created, which checks the changes included by executing all tests.
24 | - A CI build is triggered when any change is commited in `develop` branch, which generates CI packages (e.g., *.3.0.0-ci-20200612.1.nupkg)
25 | - A preview release build is triggered when any change is commited in `master` branch, which generates and publishes preview packages (e.g., *.3.0.0-preview-20200612.1.nupkg) to nuget.org
26 | - To publish a stable release repository owner manually trigger a stable release build in Azure DevOps which generates stable packages and publishes to nuget.org (e.g., *.3.0.0.nupkg)
27 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting/IpcBackgroundService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Hosting;
2 | using Microsoft.Extensions.Logging;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace JKang.IpcServiceFramework.Hosting
9 | {
10 | public sealed class IpcBackgroundService : BackgroundService
11 | {
12 | private readonly IEnumerable _endpoints;
13 | private readonly ILogger _logger;
14 |
15 | public IpcBackgroundService(
16 | IEnumerable endpoints,
17 | ILogger logger)
18 | {
19 | _endpoints = endpoints ?? throw new System.ArgumentNullException(nameof(endpoints));
20 | _logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
21 | }
22 |
23 | protected override Task ExecuteAsync(CancellationToken stoppingToken)
24 | {
25 | return Task.WhenAll(_endpoints.Select(x => x.ExecuteAsync(stoppingToken)));
26 | }
27 |
28 | public override void Dispose()
29 | {
30 | foreach (IIpcEndpoint endpoint in _endpoints)
31 | {
32 | endpoint.Dispose();
33 | }
34 |
35 | base.Dispose();
36 | _logger.LogInformation("IPC background service disposed.");
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/samples/IpcServiceSample.Client/Program.cs:
--------------------------------------------------------------------------------
1 | using IpcServiceSample.ServiceContracts;
2 | using JKang.IpcServiceFramework.Client;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using System;
5 | using System.Threading.Tasks;
6 |
7 | namespace IpcServiceSample.ConsoleClient
8 | {
9 | class Program
10 | {
11 | private static async Task Main(string[] args)
12 | {
13 | while (true)
14 | {
15 | Console.WriteLine("Type a phrase and press enter or press Ctrl+C to exit:");
16 | string input = Console.ReadLine();
17 |
18 | // register IPC clients
19 | ServiceProvider serviceProvider = new ServiceCollection()
20 | .AddNamedPipeIpcClient("client1", pipeName: "pipeinternal")
21 | .BuildServiceProvider();
22 |
23 | // resolve IPC client factory
24 | IIpcClientFactory clientFactory = serviceProvider
25 | .GetRequiredService>();
26 |
27 | // create client
28 | IIpcClient client = clientFactory.CreateClient("client1");
29 |
30 | string output = await client.InvokeAsync(x => x.ReverseString(input));
31 |
32 | Console.WriteLine($"Result from server: '{output}'.\n");
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client/IpcStreamWrapper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Text;
5 | using System.Threading;
6 |
7 | namespace JKang.IpcServiceFramework.Client
8 | {
9 | ///
10 | /// Tcp clients depend on both a TcpClient object and a Stream object.
11 | /// This wrapper class ensures they are simultaneously disposed of.
12 | ///
13 | ///
14 | public class IpcStreamWrapper : IDisposable
15 | {
16 | private IDisposable _context;
17 | bool _disposed = false;
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | /// The stream.
23 | /// The IDisposable context the Stream depends on.
24 | public IpcStreamWrapper(Stream stream, IDisposable context = null)
25 | {
26 | Stream = stream;
27 | _context = context;
28 | }
29 |
30 | public Stream Stream { get; private set; }
31 |
32 | public void Dispose()
33 | {
34 | if (!_disposed)
35 | {
36 | _disposed = true;
37 | Stream?.Dispose();
38 | _context?.Dispose();
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client/IpcClientOptions.cs:
--------------------------------------------------------------------------------
1 | using JKang.IpcServiceFramework.Services;
2 | using System;
3 | using System.IO;
4 |
5 | namespace JKang.IpcServiceFramework.Client
6 | {
7 | public class IpcClientOptions
8 | {
9 | public Func StreamTranslator { get; set; }
10 |
11 | ///
12 | /// The number of milliseconds to wait for the server to respond before
13 | /// the connection times out. Default value is 60000.
14 | ///
15 | public int ConnectionTimeout { get; set; } = 60000;
16 |
17 | ///
18 | /// Indicates the method that will be used during deserialization on the server for locating and loading assemblies.
19 | /// If false, the assembly used during deserialization must match exactly the assembly used during serialization.
20 | ///
21 | /// If true, the assembly used during deserialization need not match exactly the assembly used during serialization.
22 | /// Specifically, the version numbers need not match.
23 | ///
24 | /// Default is false.
25 | ///
26 | public bool UseSimpleTypeNameAssemblyFormatHandling { get; set; } = false;
27 |
28 | public IIpcMessageSerializer Serializer { get; set; } = new DefaultIpcMessageSerializer();
29 |
30 | public IValueConverter ValueConverter { get; set; } = new DefaultValueConverter();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting.NamedPipe/NamedPipeIpcHostBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using JKang.IpcServiceFramework.Hosting.NamedPipe;
2 | using Microsoft.Extensions.DependencyInjection;
3 | using Microsoft.Extensions.Logging;
4 | using System;
5 |
6 | namespace JKang.IpcServiceFramework.Hosting
7 | {
8 | public static class NamedPipeIpcHostBuilderExtensions
9 | {
10 | public static IIpcHostBuilder AddNamedPipeEndpoint(this IIpcHostBuilder builder,
11 | string pipeName)
12 | where TContract : class
13 | {
14 | return builder.AddNamedPipeEndpoint(options =>
15 | {
16 | options.PipeName = pipeName;
17 | });
18 | }
19 |
20 | public static IIpcHostBuilder AddNamedPipeEndpoint(this IIpcHostBuilder builder,
21 | Action configure)
22 | where TContract : class
23 | {
24 | var options = new NamedPipeIpcEndpointOptions();
25 | configure?.Invoke(options);
26 |
27 | builder.AddIpcEndpoint(serviceProvider =>
28 | {
29 | ILogger> logger = serviceProvider
30 | .GetRequiredService>>();
31 |
32 | return new NamedPipeIpcEndpoint(options, logger, serviceProvider);
33 | });
34 |
35 | return builder;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client/IpcClientRegistration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace JKang.IpcServiceFramework.Client
4 | {
5 | public class IpcClientRegistration
6 | where TContract: class
7 | where TIpcClientOptions: IpcClientOptions
8 | {
9 | private readonly Func> _clientFactory;
10 | private readonly Action _configureOptions;
11 |
12 | public IpcClientRegistration(string name,
13 | Func> clientFactory,
14 | Action configureOptions)
15 | {
16 | Name = name;
17 | _clientFactory = clientFactory ?? throw new ArgumentNullException(nameof(clientFactory));
18 | _configureOptions = configureOptions;
19 | }
20 |
21 | public string Name { get; }
22 |
23 | public IIpcClient CreateClient(IServiceProvider serviceProvider)
24 | {
25 | if (serviceProvider is null)
26 | {
27 | throw new ArgumentNullException(nameof(serviceProvider));
28 | }
29 |
30 | TIpcClientOptions options = Activator.CreateInstance();
31 | _configureOptions?.Invoke(serviceProvider, options);
32 | return _clientFactory.Invoke(serviceProvider, options);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Hosting.Tcp/TcpIpcHostBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using JKang.IpcServiceFramework.Hosting.Tcp;
2 | using Microsoft.Extensions.DependencyInjection;
3 | using Microsoft.Extensions.Logging;
4 | using System;
5 | using System.Net;
6 |
7 | namespace JKang.IpcServiceFramework.Hosting
8 | {
9 | public static class TcpIpcHostBuilderExtensions
10 | {
11 | public static IIpcHostBuilder AddTcpEndpoint(this IIpcHostBuilder builder,
12 | IPAddress ipEndpoint, int port)
13 | where TContract : class
14 | {
15 | return builder.AddTcpEndpoint(options =>
16 | {
17 | options.IpEndpoint = ipEndpoint;
18 | options.Port = port;
19 | });
20 | }
21 |
22 | public static IIpcHostBuilder AddTcpEndpoint(this IIpcHostBuilder builder,
23 | Action configure)
24 | where TContract : class
25 | {
26 | var options = new TcpIpcEndpointOptions();
27 | configure?.Invoke(options);
28 |
29 | builder.AddIpcEndpoint(serviceProvider =>
30 | {
31 | ILogger> logger = serviceProvider
32 | .GetRequiredService>>();
33 |
34 | return new TcpIpcEndpoint(options, logger, serviceProvider);
35 | });
36 |
37 | return builder;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client/IpcClientFactory.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace JKang.IpcServiceFramework.Client
7 | {
8 | internal class IpcClientFactory : IIpcClientFactory
9 | where TContract : class
10 | where TIpcClientOptions : IpcClientOptions
11 | {
12 | private readonly IServiceProvider _serviceProvider;
13 | private readonly IEnumerable> _registrations;
14 |
15 | public IpcClientFactory(
16 | IServiceProvider serviceProvider,
17 | IEnumerable> registrations)
18 | {
19 | _serviceProvider = serviceProvider;
20 | _registrations = registrations;
21 | }
22 |
23 | public IIpcClient CreateClient(string name)
24 | {
25 | IpcClientRegistration registration = _registrations.FirstOrDefault(x => x.Name == name);
26 | if (registration == null)
27 | {
28 | throw new ArgumentException($"IPC client '{name}' is not configured.", nameof(name));
29 | }
30 |
31 | using (IServiceScope scope = _serviceProvider.CreateScope())
32 | {
33 | return registration.CreateClient(scope.ServiceProvider);
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.NamedPipeTests/Fixtures/XorStream.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace JKang.IpcServiceFramework.Testing.Fixtures
4 | {
5 | public class XorStream : Stream
6 | {
7 | private readonly Stream _baseStream;
8 |
9 | public XorStream(Stream stream)
10 | {
11 | _baseStream = stream;
12 | }
13 |
14 | public override bool CanRead => _baseStream.CanRead;
15 |
16 | public override bool CanSeek => _baseStream.CanSeek;
17 |
18 | public override bool CanWrite => _baseStream.CanWrite;
19 |
20 | public override long Length => _baseStream.Length;
21 |
22 | public override long Position { get => _baseStream.Position; set => _baseStream.Position = value; }
23 |
24 | public override void Flush()
25 | {
26 | _baseStream.Flush();
27 | }
28 |
29 | public override int Read(byte[] buffer, int offset, int count)
30 | {
31 | int br = _baseStream.Read(buffer, offset, count);
32 | for (int i = offset; i < offset + br; i++)
33 | {
34 | buffer[i] ^= 0xFF;
35 | }
36 |
37 | return br;
38 | }
39 |
40 | public override long Seek(long offset, SeekOrigin origin)
41 | {
42 | return _baseStream.Seek(offset, origin);
43 | }
44 |
45 | public override void SetLength(long value)
46 | {
47 | _baseStream.SetLength(value);
48 | }
49 |
50 | public override void Write(byte[] buffer, int offset, int count)
51 | {
52 | byte[] xoredBuffer = new byte[count];
53 | for (int i = 0; i < count; i++)
54 | {
55 | xoredBuffer[i] = (byte)(buffer[offset + i] ^ 0xFF);
56 | }
57 |
58 | _baseStream.Write(xoredBuffer, 0, count);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/Services/DefaultIpcMessageSerializer.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Text;
4 |
5 | namespace JKang.IpcServiceFramework.Services
6 | {
7 | public class DefaultIpcMessageSerializer : IIpcMessageSerializer
8 | {
9 | private static readonly JsonSerializerSettings _settings = new JsonSerializerSettings
10 | {
11 | TypeNameHandling = TypeNameHandling.Objects
12 | };
13 |
14 | public IpcRequest DeserializeRequest(byte[] binary)
15 | {
16 | return Deserialize(binary);
17 | }
18 |
19 | public IpcResponse DeserializeResponse(byte[] binary)
20 | {
21 | return Deserialize(binary);
22 | }
23 |
24 | public byte[] SerializeRequest(IpcRequest request)
25 | {
26 | return Serialize(request);
27 | }
28 |
29 | public byte[] SerializeResponse(IpcResponse response)
30 | {
31 | return Serialize(response);
32 | }
33 |
34 | private T Deserialize(byte[] binary)
35 | {
36 | try
37 | {
38 | string json = Encoding.UTF8.GetString(binary);
39 | return JsonConvert.DeserializeObject(json, _settings);
40 | }
41 | catch (Exception ex) when (
42 | ex is JsonSerializationException ||
43 | ex is ArgumentException ||
44 | ex is EncoderFallbackException)
45 | {
46 | throw new IpcSerializationException("Failed to deserialize IPC message", ex);
47 | }
48 | }
49 |
50 | private byte[] Serialize(object obj)
51 | {
52 | try
53 | {
54 | string json = JsonConvert.SerializeObject(obj, _settings);
55 | return Encoding.UTF8.GetBytes(json);
56 | }
57 | catch (Exception ex) when (
58 | ex is JsonSerializationException ||
59 | ex is EncoderFallbackException)
60 | {
61 | throw new IpcSerializationException("Failed to serialize IPC message", ex);
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Client.Tcp/TcpIpcClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net.Security;
4 | using System.Net.Sockets;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace JKang.IpcServiceFramework.Client.Tcp
9 | {
10 | internal class TcpIpcClient : IpcClient
11 | where TInterface : class
12 | {
13 | private readonly TcpIpcClientOptions _options;
14 |
15 | public TcpIpcClient(string name, TcpIpcClientOptions options)
16 | : base(name, options)
17 | {
18 | _options = options ?? throw new ArgumentNullException(nameof(options));
19 | }
20 |
21 | protected override Task ConnectToServerAsync(CancellationToken cancellationToken)
22 | {
23 | cancellationToken.ThrowIfCancellationRequested();
24 | #pragma warning disable CA2000 // Dispose objects before losing scope. Disposed by IpcStreamWrapper
25 | TcpClient client = new TcpClient();
26 | #pragma warning restore CA2000 // Dispose objects before losing scope
27 |
28 | if (!client.ConnectAsync(_options.ServerIp, _options.ServerPort)
29 | .Wait(_options.ConnectionTimeout, cancellationToken))
30 | {
31 | client.Close();
32 | cancellationToken.ThrowIfCancellationRequested();
33 | throw new TimeoutException();
34 | }
35 |
36 | Stream stream = client.GetStream();
37 |
38 | // if SSL is enabled, wrap the stream in an SslStream in client mode
39 | if (_options.EnableSsl)
40 | {
41 | SslStream ssl;
42 | if (_options.SslValidationCallback == null)
43 | {
44 | ssl = new SslStream(stream, false);
45 | }
46 | else
47 | {
48 | ssl = new SslStream(stream, false, _options.SslValidationCallback);
49 | }
50 |
51 | // set client mode and specify the common name(CN) of the server
52 | if (_options.SslServerIdentity != null)
53 | {
54 | ssl.AuthenticateAsClient(_options.SslServerIdentity);
55 | }
56 | stream = ssl;
57 | }
58 |
59 | return Task.FromResult(new IpcStreamWrapper(stream, client));
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/JKang.IpcServiceFramework.Core/IpcRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Reflection;
4 | using System.Runtime.Serialization;
5 |
6 | namespace JKang.IpcServiceFramework
7 | {
8 | [DataContract]
9 | public class IpcRequest
10 | {
11 | [DataMember]
12 | public string MethodName { get; set; }
13 |
14 | [DataMember]
15 | public IEnumerable