https://github.com/uipath/coreipc
WCF-like service model API for communication over named pipes, TCP and web sockets. .NET and node.js clients.
https://github.com/uipath/coreipc
ipc json-rpc netcore rpc wcf
Last synced: 5 months ago
JSON representation
WCF-like service model API for communication over named pipes, TCP and web sockets. .NET and node.js clients.
- Host: GitHub
- URL: https://github.com/uipath/coreipc
- Owner: UiPath
- License: mit
- Created: 2019-08-01T13:55:27.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-12-12T11:33:20.000Z (over 1 year ago)
- Last Synced: 2025-01-12T10:10:17.017Z (about 1 year ago)
- Topics: ipc, json-rpc, netcore, rpc, wcf
- Homepage:
- Size: 163 MB
- Stars: 30
- Watchers: 15
- Forks: 9
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# UiPath.Ipc
[](https://uipath.visualstudio.com/CoreIpc/_build?definitionId=637)
[](https://uipath.visualstudio.com/Public.Feeds/_artifacts/feed/UiPath-Internal/NuGet/UiPath.Ipc/overview/2.5.1-20250714-01)
[](https://github.com/UiPath/coreipc/pkgs/npm/coreipc)
[](https://github.com/UiPath/coreipc/pkgs/npm/coreipc-web)
[](https://opensource.org/licenses/MIT)
> **Lightweight RPC framework** enabling bidirectional communication with interface-based contracts over **Named Pipes, TCP/IP, and WebSockets**. Supports .NET servers/clients and [Node.js/Web clients](src/Clients/js).
## 🚀 Features
- **🔄 Asynchronous**: Fully async/await compatible API
- **🔥 One-way Calls**: Fire-and-forget methods (methods returning non-generic `Task`)
- **📞 Callbacks**: Bidirectional communication with callback interfaces
- **⚡ Task Scheduling**: Configurable task scheduler support
- **📡 Multiple Transports**: Named Pipes, TCP/IP, WebSockets or custom transport
- **🔒 Security**: Client authentication and impersonation for Named Pipes
- **📦 JSON Serialization**: Built-in JSON serialization with Newtonsoft.Json
- **🏗️ DI Support**: Integration with Microsoft.Extensions.DependencyInjection
- **⏰ Cancellation & Timeouts**: Comprehensive cancellation token and timeout support
- **🔄 Auto-reconnect**: Broken connections are re-established transparently; you keep using the same proxy instance.
- **🛡️ Interception**: BeforeConnect, BeforeIncommingCall and BeforeOutgoingCall interception capabilities
- **📊 Stream Access**: Direct access to underlying transport streams
- **🌐 Cross-platform**: .NET 6, .NET Framework 4.6.1, and .NET 6 Windows support
## 📦 Installation
```bash
dotnet add package UiPath.Ipc
```
## 🏃♂️ Quick Start
### 1. Define Your Service Contract
```csharp
public interface IComputingService
{
Task AddFloats(float x, float y, Message m = null!, CancellationToken ct = default);
Task Wait(TimeSpan duration, CancellationToken ct = default);
}
public interface IComputingCallback
{
Task GetThreadName();
}
```
### 2. Implement Your Service
```csharp
public sealed class ComputingService : IComputingService
{
public async Task AddFloats(float a, float b, Message m = null!, CancellationToken ct = default)
{
return a + b;
}
public async Task Wait(TimeSpan duration, CancellationToken ct = default)
{
await Task.Delay(duration, ct);
return true;
}
}
```
### 3. Create and Start the Server
> Creating a server is done by instantiating the `IpcServer` class, setting its properties and calling the `Start` method.
```csharp
await using var serviceProvider = new ServiceCollection()
.AddScoped()
.BuildServiceProvider();
await using var server = new IpcServer
{
Transport = new NamedPipeServerTransport { PipeName = "computing" },
ServiceProvider = serviceProvider,
Endpoints = new() { typeof(IComputingService) }
};
server.Start();
await server.WaitForStart();
```
### 3. Create the Client
> Creating a client is done by 1st implementing all the callback interfaces you'll want to expose as a client:
```csharp
public sealed class ComputingCallback : IComputingCallback
{
public Task GetThreadName() => Task.FromResult(Thread.CurrentThread.Name);
}
```
and then instantiating the `IpcClient`, setting its properties, obtaining a proxy via the `GetProxy` method and using that proxy.
```csharp
await using var serviceProvider = new ServiceCollection()
.AddScoped()
.BuildServiceProvider();
var client = new IpcClient
{
Transport = new NamedPipeClientTransport { PipeName = "computing" },
ServiceProvider = serviceProvider,
Callbacks = new() { typeof(IComputingCallback) }
}
var computingService = client.GetProxy();
var three = await computingService.AddFloats(1, 2);
```
## 🔧 Advanced Features
### Callbacks and Bidirectional Communication
```csharp
public class ComputingCallback : IComputingCallback
{
public async Task GetThreadName()
{
return Thread.CurrentThread.Name ?? "Unknown";
}
public async Task AddInts(int x, int y)
{
return x + y;
}
}
// Server can call back to client
public async Task GetCallbackThreadName(TimeSpan waitOnServer, Message message, CancellationToken cancellationToken)
{
await Task.Delay(waitOnServer, cancellationToken);
return await message.Client.GetCallback().GetThreadName();
}
```
### Dependency Injection Integration
```csharp
var services = new ServiceCollection()
.AddLogging(builder => builder.AddConsole())
.AddSingleton()
.AddSingleton()
.BuildServiceProvider();
var ipcServer = new IpcServer
{
ServiceProvider = services,
// ... other configuration
};
```
### Custom Task Scheduling
```csharp
var ipcServer = new IpcServer
{
Scheduler = new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler,
// ... other configuration
};
```
## 🧩 Notable Types
### 1. The `IpcServer`, `IpcClient` and `IpcBase` classes.
> This hierarchy is used for creating and hosting servers and clients respectively.
> ```csharp
> public abstract class IpcBase { ... }
> public sealed class IpcServer : IpcBase { ... }
> public sealed class IpcClient : IpcBase { ... }
> ```

#### i. `IpcBase`
> This class defines the settings shared between servers and clients.
| Property | Type | Notes |
| -------- | ---- | ----- |
| ServiceProvider | IServiceProvider? | **Optional**, defaults to **null**: Resolves services when handling incomming calls. |
| Scheduler | TaskScheduler? | **Optional**, defaults to the thread pool: Schedules incomming calls. |
| RequestTimeout | TimeSpan? | **Optional**, defaults to infinity: Interval after which the honoring of requests will time out. |
#### ii. `IpcServer`
**Declared properties**
| Property | Type | Notes |
| -------- | ---- | ----- |
| Endpoints | ContractCollection | **Required**: The collection of `ContractSettings`, which specifies the services to be exposed over Ipc. |
| Transport | ServerTransport | **Required**: The server's transport, meaning whether it accepts connection over Named Pipes, TCP/IP, WebSockets, or a custom communication mechanism. |
**Methods**
| Method | Description |
| ------ | ----------- |
| `void Start()` | This method starts hosting the current `IpcServer` instance, meaning that it's imminent the transport will start listening and accepting connections, and those connections' calls will start to be honored.
It's thread-safe, idempotent and fire&forget in nature, meaning it doesn't wait for the listener to become active. Further changes to the otherwise mutable `IpcServer` instance have no effect on the listener's settings or its exposed service collection.
Exceptions:
- `InvalidOperationException`: wrong configurations, such a `null` or invalid transport.
- `ObjectDisposedException`: the `IpcServer` instance had been disposed. |
| `Task WaitForStart()` | This method calls `Start` and then awaits for the connection accepter to start. It's thread-safe and idempotent. |
| `ValueTask DisposeAsync()` | Stops the connection accepter and cancels all active connections before completing the returned `ValueTask`. |
#### iii. `IpcClient`
**Declared properties*
| Property | Type | Notes |
| -------- | ---- | ----- |
| Callbacks | ContractCollection | **Optional**: The collection of `ContractSettings`, which specifies the services to be exposed over Ipc **as callbacks**. |
| Transport | ClientTransport | **Required**: The client's transport, meaning whether it connects to the server over Named Pipes, TCP/IP, WebSockets, or a custom communication mechanism. |
**Methods**
| Method | Notes |
| ------ | ----- |
| `TProxy GetProxy() where TProxy : class` | Returns an Ipc proxy of the specified type, which is the gateway for remote calling. This method is idempotent, meaning that it will cache its result. |
### 2. The `ContractCollection` and `ContractSettings` classes.
#### i. `ContractCollection`
> `ContractCollection` is a type-safe collection that holds `ContractSettings` instances, mapping service interface types to their configuration. It implements `IEnumerable` and provides convenient `Add` methods for different scenarios.
**Add Methods:**
| Method | Description |
| ------ | ----------- |
| `Add(Type contractType)` | Adds a contract type that will be resolved from the service provider when needed (deferred resolution). |
| `Add(Type contractType, object? instance)` | Adds a contract type with a specific service instance. If `instance` is `null`, uses deferred resolution. |
| `Add(ContractSettings endpointSettings)` | Adds a pre-configured `ContractSettings` instance directly. |
#### ii. `ContractSettings`
> `ContractSettings` represents the configuration for a single service contract, including how the service instance is created/resolved, task scheduling, and call interception.
**Properties:**
| Property | Type | Description |
| -------- | ---- | ----------- |
| `Scheduler` | `TaskScheduler?` | **Optional**: Custom task scheduler for this specific contract. Inherits from `IpcBase.Scheduler` if not set. |
| `BeforeIncomingCall` | `BeforeCallHandler?` | **Optional**: Interceptor called before each incoming method call on this contract. |
**Constructors:**
| Constructor | Description |
| ----------- | ----------- |
| `ContractSettings(Type contractType, object? serviceInstance = null)` | Creates settings for a contract type with optional direct service instance. If `serviceInstance` is `null`, uses deferred resolution. |
| `ContractSettings(Type contractType, IServiceProvider serviceProvider)` | Creates settings for a contract type with explicit service provider for dependency injection. |
**Service Resolution Strategies:**
- **Direct Instance**: When you provide a service instance, that exact instance is used for all calls
- **Deferred Resolution**: When no instance is provided, the service is resolved from the `IpcServer`'s `ServiceProvider` when needed
- **Injected Resolution**: When you provide a specific `IServiceProvider`, services are resolved from that provider
**Usage Examples:**
```csharp
// Direct instance
var settings1 = new ContractSettings(typeof(IComputingService), new ComputingService());
// Deferred resolution (will use IpcServer.ServiceProvider)
var settings2 = new ContractSettings(typeof(IComputingService));
// Custom service provider
var customProvider = new ServiceCollection()
.AddTransient()
.BuildServiceProvider();
var settings3 = new ContractSettings(typeof(IComputingService), customProvider);
// With advanced configuration
var settings4 = new ContractSettings(typeof(IComputingService))
{
Scheduler = new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler,
BeforeIncomingCall = async (callInfo, ct) =>
{
Console.WriteLine($"Calling {callInfo.Method.Name}");
}
};
```