-
-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #138 from jacqueskang/develop
v3.0.0
- Loading branch information
Showing
146 changed files
with
3,118 additions
and
2,876 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# These are supported funding model platforms | ||
|
||
github: jacqueskang | ||
patreon: # Replace with a single Patreon username | ||
open_collective: # Replace with a single Open Collective username | ||
ko_fi: # Replace with a single Ko-fi username | ||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel | ||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry | ||
liberapay: # Replace with a single Liberapay username | ||
issuehunt: # Replace with a single IssueHunt username | ||
otechie: # Replace with a single Otechie username | ||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,163 +1,106 @@ | ||
[![Build Status](https://travis-ci.org/jacqueskang/IpcServiceFramework.svg?branch=develop)](https://travis-ci.org/jacqueskang/IpcServiceFramework) | ||
| CI build | Stable build | | ||
|----------|--------------| | ||
|[![Build Status](https://dev.azure.com/jacques-kang/IpcServiceFramework/_apis/build/status/IpcServiceFramework%20CI?branchName=develop)](https://dev.azure.com/jacques-kang/IpcServiceFramework/_build/latest?definitionId=9&branchName=develop)|[![Build Status](https://dev.azure.com/jacques-kang/IpcServiceFramework/_apis/build/status/IpcServiceFramework?branchName=master)](https://dev.azure.com/jacques-kang/IpcServiceFramework/_build/latest?definitionId=14&branchName=master)| | ||
|
||
# IpcServiceFramework | ||
|
||
A .NET Core lightweight inter-process communication framework allowing invoking a service via named pipeline and/or TCP (in a similar way as WCF, which is currently unavailable for .NET Core). Secure communication over SSL is also supported. | ||
|
||
Support using primitive or complex types in service contract. | ||
|
||
Support multi-threading on server side with configurable number of threads (named pipeline endpoint only). | ||
|
||
[ASP.NET Core Dependency Injection framework](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection) friendly. | ||
A .NET Core 3.1 based lightweight framework for efficient inter-process communication. | ||
Named pipeline and TCP support out-of-the-box, extensible with other protocols. | ||
|
||
## Usage | ||
1. Create an interface as service contract and package it in an assembly to be shared between server and client. | ||
2. Implement the service and host it in an console or web applciation. | ||
3. Invoke the service with framework provided proxy client. | ||
|
||
## Downloads | ||
|
||
IpcServiceFramework is available via NuGet: | ||
1. Create an interface as service contract and package it in an assembly to be referenced by server and client applications, for example: | ||
|
||
- [JKang.IpcServiceFramework.Server](https://www.nuget.org/packages/JKang.IpcServiceFramework.Server/) | ||
- [JKang.IpcServiceFramework.Client](https://www.nuget.org/packages/JKang.IpcServiceFramework.Client/) | ||
|
||
## Quick Start: | ||
|
||
### Step 1: Create service contract | ||
```csharp | ||
public interface IComputingService | ||
```csharp | ||
public interface IInterProcessService | ||
{ | ||
float AddFloat(float x, float y); | ||
string ReverseString(string input); | ||
} | ||
``` | ||
_Note: This interface is ideally to be placed in a library assembly to be shared between server and client._ | ||
|
||
### Step 2: Implement the server | ||
|
||
1. Create a console application with the following 2 NuGet packages installed: | ||
``` | ||
|
||
``` | ||
> Install-Package Microsoft.Extensions.DependencyInjection | ||
> Install-Package JKang.IpcServiceFramework.Server | ||
``` | ||
|
||
2. Add an class that implements the service contract | ||
|
||
```csharp | ||
class ComputingService : IComputingService | ||
1. Implement the service in server application, for example: | ||
|
||
```csharp | ||
class InterProcessService : IInterProcessService | ||
{ | ||
public float AddFloat(float x, float y) | ||
public string ReverseString(string input) | ||
{ | ||
return x + y; | ||
char[] charArray = input.ToCharArray(); | ||
Array.Reverse(input.ToCharArray()); | ||
return new string(charArray); | ||
} | ||
} | ||
``` | ||
``` | ||
|
||
1. Install the following NuGet packages in server application: | ||
|
||
3. Configure and run the server | ||
```powershell | ||
> Install-Package Microsoft.Extensions.Hosting | ||
> Install-Package JKang.IpcServiceFramework.Hosting.NamedPipe | ||
``` | ||
|
||
```csharp | ||
1. Register the service implementation and configure IPC endpoint(s): | ||
|
||
```csharp | ||
class Program | ||
{ | ||
static void Main(string[] args) | ||
public static void Main(string[] args) | ||
{ | ||
// configure DI | ||
IServiceCollection services = ConfigureServices(new ServiceCollection()); | ||
|
||
// build and run service host | ||
new IpcServiceHostBuilder(services.BuildServiceProvider()) | ||
.AddNamedPipeEndpoint<IComputingService>(name: "endpoint1", pipeName: "pipeName") | ||
.AddTcpEndpoint<IComputingService>(name: "endpoint2", ipEndpoint: IPAddress.Loopback, port: 45684) | ||
.Build() | ||
.Run(); | ||
CreateHostBuilder(args).Build().Run(); | ||
} | ||
|
||
private static IServiceCollection ConfigureServices(IServiceCollection services) | ||
{ | ||
return services | ||
.AddIpc(builder => | ||
public static IHostBuilder CreateHostBuilder(string[] args) => | ||
Host.CreateDefaultBuilder(args) | ||
.ConfigureServices(services => | ||
{ | ||
builder | ||
.AddNamedPipe(options => | ||
{ | ||
options.ThreadCount = 2; | ||
}) | ||
.AddService<IComputingService, ComputingService>(); | ||
services.AddScoped<IInterProcessService, InterProcessService>(); | ||
}) | ||
.ConfigureIpcHost(builder => | ||
{ | ||
// configure IPC endpoints | ||
builder.AddNamedPipeEndpoint<IInterProcessService>(pipeName: "my-pipe"); | ||
}) | ||
.ConfigureLogging(builder => | ||
{ | ||
// optionally configure logging | ||
builder.SetMinimumLevel(LogLevel.Information); | ||
}); | ||
} | ||
} | ||
``` | ||
_Note: It's possible to host IPC service in web application, please check out the sample project *IpcServiceSample.WebServer*_ | ||
|
||
### Step 3: Invoke the service from client process | ||
``` | ||
|
||
1. Install the following package in client application: | ||
```bash | ||
$ dotnet add package JKang.IpcServiceFramework.Client | ||
``` | ||
1. Install the following NuGet package in client application: | ||
|
||
2. Add reference to the assembly created in step 1 which contains `IComputingService` interface. | ||
```powershell | ||
> Install-Package JKang.IpcServiceFramework.Client.NamedPipe | ||
``` | ||
|
||
3. Invoke the server | ||
1. Invoke the server | ||
|
||
```csharp | ||
IpcServiceClient<IComputingService> client = new IpcServiceClientBuilder<IComputingService>() | ||
.UseNamedPipe("pipeName") // or .UseTcp(IPAddress.Loopback, 45684) to invoke using TCP | ||
.Build(); | ||
```csharp | ||
// register IPC clients | ||
ServiceProvider serviceProvider = new ServiceCollection() | ||
.AddNamedPipeIpcClient<IInterProcessService>("client1", pipeName: "pipeinternal") | ||
.BuildServiceProvider(); | ||
|
||
float result = await client.InvokeAsync(x => x.AddFloat(1.23f, 4.56f)); | ||
``` | ||
// resolve IPC client factory | ||
IIpcClientFactory<IInterProcessService> clientFactory = serviceProvider | ||
.GetRequiredService<IIpcClientFactory<IInterProcessService>>(); | ||
|
||
__Welcome to raise any issue or even provide any suggestion/PR to participate this project!__ | ||
// create client | ||
IIpcClient<IInterProcessService> client = clientFactory.CreateClient("client1"); | ||
|
||
## Security | ||
string output = await client.InvokeAsync(x => x.ReverseString(input)); | ||
``` | ||
|
||
If you are running IPC channels over TCP on an untrusted network, you should consider using SSL. IpcServiceFramework supports SSL on TCP clients and hosts. | ||
|
||
### Generate certificates for testing | ||
|
||
**Do not use the provided certificates in the project folder.** These are used for example purposes only. | ||
|
||
For testing, you can generate a self-signed certificate using the following openssl command: | ||
|
||
openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.cer -days 365 | ||
|
||
This generates a key and a certificate that can be used for testing. | ||
|
||
### Setting up the SSL endpoint | ||
|
||
The endpoint requires a PKCS12 file containing both the certificate and a corresponding private key. | ||
|
||
A certificate and key can be combined to a PKCS12 file for use with the server using the following command: | ||
|
||
openssl pkcs12 -export -in cert.cer -inkey key.pem -out server.pfx | ||
|
||
You will be asked for a password. | ||
|
||
You can import the certificate and provide it to the server endpoint using code similar to the following: | ||
|
||
var certificate = new X509Certificate2(@"path\to\server.pfx", "password"); | ||
serviceHostBuilder.AddTcpEndpoint<ISomeServiceContract>("someEndpoint", ip, port, certificate); | ||
|
||
See the ConsoleServer and WebServer projects for more complete examples. | ||
|
||
Note: for security and maintenance reasons, we do not recommend that you hard-code the certificate password. It should instead be stored in the application configuration file so that it can be easily changed. | ||
|
||
### Safe usage | ||
|
||
SSL/TLS is only secure if you use it properly. Here are some tips: | ||
|
||
* For production purposes, use a proper server certificate, signed by a real certificate authority (CA) or your organisation's internal CA. Do not use self-signed certificates in production. | ||
* Do not use custom certificate validation callbacks on the client. They are hard to implement correctly and tend to result in security issues. | ||
* Unconditionally returning true in a validation callback provides no security whatsoever against an attacker who can perform man-in-the-middle attacks. | ||
* The callback used in the ConsoleServer project example is not secure. It checks for the correct certificate by hash but does not check its validity, expiry date, revocation status, or other important security properties. | ||
## Downloads | ||
|
||
### Client certificates | ||
IpcServiceFramework is available via NuGet packages: | ||
|
||
Client certificates are not currently supported. | ||
- [JKang.IpcServiceFramework.Hosting.NamedPipe](https://www.nuget.org/packages/JKang.IpcServiceFramework.Hosting.NamedPipe/) | ||
- [JKang.IpcServiceFramework.Client.NamedPipe](https://www.nuget.org/packages/JKang.IpcServiceFramework.Client.NamedPipe/) | ||
- [JKang.IpcServiceFramework.Hosting.Tcp](https://www.nuget.org/packages/JKang.IpcServiceFramework.Hosting.Tcp/) | ||
- [JKang.IpcServiceFramework.Client.Tcp](https://www.nuget.org/packages/JKang.IpcServiceFramework.Client.Tcp/) | ||
## Stream translators | ||
## FAQs | ||
|
||
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, Stream>` 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. | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
variables: | ||
- template: version.yml | ||
|
||
name: $(version)-ci-$(Date:yyyyMMdd)$(Rev:.r) | ||
|
||
trigger: | ||
branches: | ||
include: | ||
- develop | ||
|
||
pr: none | ||
|
||
pool: | ||
vmImage: 'ubuntu-16.04' | ||
|
||
steps: | ||
- template: templates/build-test.yml | ||
parameters: | ||
buildConfiguration: Release | ||
|
||
- template: templates/pack-publish.yml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
variables: | ||
- template: version.yml | ||
|
||
name: $(version)-pr-$(Date:yyyyMMdd)$(Rev:.r) | ||
|
||
trigger: none | ||
|
||
pr: | ||
branches: | ||
include: | ||
- '*' | ||
|
||
pool: | ||
vmImage: 'ubuntu-16.04' | ||
|
||
steps: | ||
- template: templates/build-test.yml | ||
parameters: | ||
buildConfiguration: Debug |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
variables: | ||
- template: version.yml | ||
|
||
name: $(version) | ||
|
||
trigger: | ||
branches: | ||
include: | ||
- master | ||
|
||
pr: none | ||
|
||
pool: | ||
vmImage: 'ubuntu-16.04' | ||
|
||
steps: | ||
- checkout: self | ||
persistCredentials: true | ||
|
||
- template: templates/build-test.yml | ||
parameters: | ||
buildConfiguration: Release | ||
|
||
- template: templates/pack-publish.yml | ||
|
||
- script: | | ||
git config --global user.name "Azure DevOps" | ||
git config --global user.email "fake@dev.azure.com" | ||
git tag -a "v$(Build.BuildNumber)" -m "v$(Build.BuildNumber)" | ||
git push origin "v$(Build.BuildNumber)" | ||
displayName: Tag source |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
parameters: | ||
- name: buildConfiguration | ||
type: string | ||
default: Release | ||
|
||
steps: | ||
- task: DotNetCoreCLI@2 | ||
displayName: Build | ||
inputs: | ||
command: 'build' | ||
projects: 'src/*.sln' | ||
arguments: '--configuration ${{parameters.buildConfiguration}}' | ||
|
||
- task: DotNetCoreCLI@2 | ||
displayName: Test | ||
inputs: | ||
command: 'test' | ||
projects: 'src/*Tests/*.csproj' | ||
arguments: '--configuration ${{parameters.buildConfiguration}}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
steps: | ||
- task: DotNetCoreCLI@2 | ||
displayName: Pack | ||
inputs: | ||
command: 'pack' | ||
packagesToPack: 'src/**/*.csproj' | ||
configuration: Release | ||
nobuild: true | ||
versioningScheme: 'byEnvVar' | ||
versionEnvVar: 'Build.BuildNumber' | ||
|
||
- task: PublishBuildArtifacts@1 | ||
inputs: | ||
PathtoPublish: '$(Build.ArtifactStagingDirectory)' | ||
ArtifactName: 'drop' | ||
publishLocation: 'Container' | ||
displayName: Publish artifacts | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
variables: | ||
version: '3.0.0' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## Stream translators | ||
|
||
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, Stream>` 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. | ||
|
||
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. |
Oops, something went wrong.