Skip to content

Commit ebb2488

Browse files
authored
Merge pull request #138 from jacqueskang/develop
v3.0.0
2 parents 2a046a5 + ac98e5f commit ebb2488

File tree

146 files changed

+3118
-2876
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

146 files changed

+3118
-2876
lines changed

.github/FUNDING.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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']

.travis.yml

-11
This file was deleted.

README.md

+69-126
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,106 @@
1-
[![Build Status](https://travis-ci.org/jacqueskang/IpcServiceFramework.svg?branch=develop)](https://travis-ci.org/jacqueskang/IpcServiceFramework)
1+
| CI build | Stable build |
2+
|----------|--------------|
3+
|[![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)|
24

35
# IpcServiceFramework
46

5-
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.
6-
7-
Support using primitive or complex types in service contract.
8-
9-
Support multi-threading on server side with configurable number of threads (named pipeline endpoint only).
10-
11-
[ASP.NET Core Dependency Injection framework](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection) friendly.
7+
A .NET Core 3.1 based lightweight framework for efficient inter-process communication.
8+
Named pipeline and TCP support out-of-the-box, extensible with other protocols.
129

1310
## Usage
14-
1. Create an interface as service contract and package it in an assembly to be shared between server and client.
15-
2. Implement the service and host it in an console or web applciation.
16-
3. Invoke the service with framework provided proxy client.
17-
18-
## Downloads
1911

20-
IpcServiceFramework is available via NuGet:
12+
1. Create an interface as service contract and package it in an assembly to be referenced by server and client applications, for example:
2113

22-
- [JKang.IpcServiceFramework.Server](https://www.nuget.org/packages/JKang.IpcServiceFramework.Server/)
23-
- [JKang.IpcServiceFramework.Client](https://www.nuget.org/packages/JKang.IpcServiceFramework.Client/)
24-
25-
## Quick Start:
26-
27-
### Step 1: Create service contract
28-
```csharp
29-
public interface IComputingService
14+
```csharp
15+
public interface IInterProcessService
3016
{
31-
float AddFloat(float x, float y);
17+
string ReverseString(string input);
3218
}
33-
```
34-
_Note: This interface is ideally to be placed in a library assembly to be shared between server and client._
35-
36-
### Step 2: Implement the server
37-
38-
1. Create a console application with the following 2 NuGet packages installed:
19+
```
3920

40-
```
41-
> Install-Package Microsoft.Extensions.DependencyInjection
42-
> Install-Package JKang.IpcServiceFramework.Server
43-
```
44-
45-
2. Add an class that implements the service contract
46-
47-
```csharp
48-
class ComputingService : IComputingService
21+
1. Implement the service in server application, for example:
22+
23+
```csharp
24+
class InterProcessService : IInterProcessService
4925
{
50-
public float AddFloat(float x, float y)
26+
public string ReverseString(string input)
5127
{
52-
return x + y;
28+
char[] charArray = input.ToCharArray();
29+
Array.Reverse(input.ToCharArray());
30+
return new string(charArray);
5331
}
5432
}
55-
```
33+
```
34+
35+
1. Install the following NuGet packages in server application:
5636

57-
3. Configure and run the server
37+
```powershell
38+
> Install-Package Microsoft.Extensions.Hosting
39+
> Install-Package JKang.IpcServiceFramework.Hosting.NamedPipe
40+
```
5841

59-
```csharp
42+
1. Register the service implementation and configure IPC endpoint(s):
43+
44+
```csharp
6045
class Program
6146
{
62-
static void Main(string[] args)
47+
public static void Main(string[] args)
6348
{
64-
// configure DI
65-
IServiceCollection services = ConfigureServices(new ServiceCollection());
66-
67-
// build and run service host
68-
new IpcServiceHostBuilder(services.BuildServiceProvider())
69-
.AddNamedPipeEndpoint<IComputingService>(name: "endpoint1", pipeName: "pipeName")
70-
.AddTcpEndpoint<IComputingService>(name: "endpoint2", ipEndpoint: IPAddress.Loopback, port: 45684)
71-
.Build()
72-
.Run();
49+
CreateHostBuilder(args).Build().Run();
7350
}
7451

75-
private static IServiceCollection ConfigureServices(IServiceCollection services)
76-
{
77-
return services
78-
.AddIpc(builder =>
52+
public static IHostBuilder CreateHostBuilder(string[] args) =>
53+
Host.CreateDefaultBuilder(args)
54+
.ConfigureServices(services =>
7955
{
80-
builder
81-
.AddNamedPipe(options =>
82-
{
83-
options.ThreadCount = 2;
84-
})
85-
.AddService<IComputingService, ComputingService>();
56+
services.AddScoped<IInterProcessService, InterProcessService>();
57+
})
58+
.ConfigureIpcHost(builder =>
59+
{
60+
// configure IPC endpoints
61+
builder.AddNamedPipeEndpoint<IInterProcessService>(pipeName: "my-pipe");
62+
})
63+
.ConfigureLogging(builder =>
64+
{
65+
// optionally configure logging
66+
builder.SetMinimumLevel(LogLevel.Information);
8667
});
87-
}
8868
}
89-
```
90-
_Note: It's possible to host IPC service in web application, please check out the sample project *IpcServiceSample.WebServer*_
91-
92-
### Step 3: Invoke the service from client process
69+
```
9370

94-
1. Install the following package in client application:
95-
```bash
96-
$ dotnet add package JKang.IpcServiceFramework.Client
97-
```
71+
1. Install the following NuGet package in client application:
9872

99-
2. Add reference to the assembly created in step 1 which contains `IComputingService` interface.
73+
```powershell
74+
> Install-Package JKang.IpcServiceFramework.Client.NamedPipe
75+
```
10076

101-
3. Invoke the server
77+
1. Invoke the server
10278

103-
```csharp
104-
IpcServiceClient<IComputingService> client = new IpcServiceClientBuilder<IComputingService>()
105-
.UseNamedPipe("pipeName") // or .UseTcp(IPAddress.Loopback, 45684) to invoke using TCP
106-
.Build();
79+
```csharp
80+
// register IPC clients
81+
ServiceProvider serviceProvider = new ServiceCollection()
82+
.AddNamedPipeIpcClient<IInterProcessService>("client1", pipeName: "pipeinternal")
83+
.BuildServiceProvider();
10784

108-
float result = await client.InvokeAsync(x => x.AddFloat(1.23f, 4.56f));
109-
```
85+
// resolve IPC client factory
86+
IIpcClientFactory<IInterProcessService> clientFactory = serviceProvider
87+
.GetRequiredService<IIpcClientFactory<IInterProcessService>>();
11088

111-
__Welcome to raise any issue or even provide any suggestion/PR to participate this project!__
89+
// create client
90+
IIpcClient<IInterProcessService> client = clientFactory.CreateClient("client1");
11291

113-
## Security
92+
string output = await client.InvokeAsync(x => x.ReverseString(input));
93+
```
11494

115-
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.
116-
117-
### Generate certificates for testing
118-
119-
**Do not use the provided certificates in the project folder.** These are used for example purposes only.
120-
121-
For testing, you can generate a self-signed certificate using the following openssl command:
122-
123-
openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.cer -days 365
124-
125-
This generates a key and a certificate that can be used for testing.
126-
127-
### Setting up the SSL endpoint
128-
129-
The endpoint requires a PKCS12 file containing both the certificate and a corresponding private key.
130-
131-
A certificate and key can be combined to a PKCS12 file for use with the server using the following command:
132-
133-
openssl pkcs12 -export -in cert.cer -inkey key.pem -out server.pfx
134-
135-
You will be asked for a password.
136-
137-
You can import the certificate and provide it to the server endpoint using code similar to the following:
138-
139-
var certificate = new X509Certificate2(@"path\to\server.pfx", "password");
140-
serviceHostBuilder.AddTcpEndpoint<ISomeServiceContract>("someEndpoint", ip, port, certificate);
141-
142-
See the ConsoleServer and WebServer projects for more complete examples.
143-
144-
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.
145-
146-
### Safe usage
147-
148-
SSL/TLS is only secure if you use it properly. Here are some tips:
149-
150-
* 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.
151-
* Do not use custom certificate validation callbacks on the client. They are hard to implement correctly and tend to result in security issues.
152-
* Unconditionally returning true in a validation callback provides no security whatsoever against an attacker who can perform man-in-the-middle attacks.
153-
* 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.
95+
## Downloads
15496

155-
### Client certificates
97+
IpcServiceFramework is available via NuGet packages:
15698

157-
Client certificates are not currently supported.
99+
- [JKang.IpcServiceFramework.Hosting.NamedPipe](https://www.nuget.org/packages/JKang.IpcServiceFramework.Hosting.NamedPipe/)
100+
- [JKang.IpcServiceFramework.Client.NamedPipe](https://www.nuget.org/packages/JKang.IpcServiceFramework.Client.NamedPipe/)
101+
- [JKang.IpcServiceFramework.Hosting.Tcp](https://www.nuget.org/packages/JKang.IpcServiceFramework.Hosting.Tcp/)
102+
- [JKang.IpcServiceFramework.Client.Tcp](https://www.nuget.org/packages/JKang.IpcServiceFramework.Client.Tcp/)
158103
159-
## Stream translators
104+
## FAQs
160105

161-
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.
162106

163-
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.

build/azure-pipelines-ci.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
variables:
2+
- template: version.yml
3+
4+
name: $(version)-ci-$(Date:yyyyMMdd)$(Rev:.r)
5+
6+
trigger:
7+
branches:
8+
include:
9+
- develop
10+
11+
pr: none
12+
13+
pool:
14+
vmImage: 'ubuntu-16.04'
15+
16+
steps:
17+
- template: templates/build-test.yml
18+
parameters:
19+
buildConfiguration: Release
20+
21+
- template: templates/pack-publish.yml

build/azure-pipelines-pr.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
variables:
2+
- template: version.yml
3+
4+
name: $(version)-pr-$(Date:yyyyMMdd)$(Rev:.r)
5+
6+
trigger: none
7+
8+
pr:
9+
branches:
10+
include:
11+
- '*'
12+
13+
pool:
14+
vmImage: 'ubuntu-16.04'
15+
16+
steps:
17+
- template: templates/build-test.yml
18+
parameters:
19+
buildConfiguration: Debug

build/azure-pipelines.yml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
variables:
2+
- template: version.yml
3+
4+
name: $(version)
5+
6+
trigger:
7+
branches:
8+
include:
9+
- master
10+
11+
pr: none
12+
13+
pool:
14+
vmImage: 'ubuntu-16.04'
15+
16+
steps:
17+
- checkout: self
18+
persistCredentials: true
19+
20+
- template: templates/build-test.yml
21+
parameters:
22+
buildConfiguration: Release
23+
24+
- template: templates/pack-publish.yml
25+
26+
- script: |
27+
git config --global user.name "Azure DevOps"
28+
git config --global user.email "[email protected]"
29+
git tag -a "v$(Build.BuildNumber)" -m "v$(Build.BuildNumber)"
30+
git push origin "v$(Build.BuildNumber)"
31+
displayName: Tag source

build/templates/build-test.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
parameters:
2+
- name: buildConfiguration
3+
type: string
4+
default: Release
5+
6+
steps:
7+
- task: DotNetCoreCLI@2
8+
displayName: Build
9+
inputs:
10+
command: 'build'
11+
projects: 'src/*.sln'
12+
arguments: '--configuration ${{parameters.buildConfiguration}}'
13+
14+
- task: DotNetCoreCLI@2
15+
displayName: Test
16+
inputs:
17+
command: 'test'
18+
projects: 'src/*Tests/*.csproj'
19+
arguments: '--configuration ${{parameters.buildConfiguration}}'

build/templates/pack-publish.yml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
steps:
2+
- task: DotNetCoreCLI@2
3+
displayName: Pack
4+
inputs:
5+
command: 'pack'
6+
packagesToPack: 'src/**/*.csproj'
7+
configuration: Release
8+
nobuild: true
9+
versioningScheme: 'byEnvVar'
10+
versionEnvVar: 'Build.BuildNumber'
11+
12+
- task: PublishBuildArtifacts@1
13+
inputs:
14+
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
15+
ArtifactName: 'drop'
16+
publishLocation: 'Container'
17+
displayName: Publish artifacts
18+

build/version.yml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
variables:
2+
version: '3.0.0'

doc/stream-translator.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
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, 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.
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.

0 commit comments

Comments
 (0)