Showing preview only (417K chars total). Download the full file or copy to clipboard to get everything.
Repository: tylerjensen/ServiceWire
Branch: master
Commit: be54ced4c019
Files: 117
Total size: 384.5 KB
Directory structure:
gitextract_ub_i6dpw/
├── .gitattributes
├── .github/
│ └── workflows/
│ └── build-and-test.yml
├── .gitignore
├── README.md
└── src/
├── Benchmarks/
│ └── ServiceWire.Benchmarks/
│ ├── ConnectionBenchmarks.cs
│ ├── INetTester.cs
│ ├── NamedPipesBenchmarks.cs
│ ├── NewtonSoftSerializer.cs
│ ├── Program.cs
│ ├── ServiceWire.Benchmarks.csproj
│ └── TcpBenchmarks.cs
├── Demo/
│ ├── DemoClient/
│ │ ├── App.config
│ │ ├── DemoClient.csproj
│ │ └── Program.cs
│ ├── DemoCommon/
│ │ ├── Contracts.cs
│ │ └── DemoCommon.csproj
│ └── DemoHost/
│ ├── App.config
│ ├── DemoHost.csproj
│ └── Program.cs
├── License.txt
├── Serializers/
│ └── ServiceWire.Serializers/
│ ├── BinaryFormatterSerializer.cs
│ └── ServiceWire.Serializers.csproj
├── ServiceWire/
│ ├── Aspects/
│ │ ├── CrossCuttingConcerns.cs
│ │ ├── InterceptChannel.cs
│ │ ├── InterceptPoint.cs
│ │ └── Interceptor.cs
│ ├── Channel.cs
│ ├── DefaultCompressor.cs
│ ├── DefaultSerializer.cs
│ ├── DefaultTypeMaker.cs
│ ├── Host.cs
│ ├── IChannelIdentifier.cs
│ ├── ICompressor.cs
│ ├── IDvChannel.cs
│ ├── ILog.cs
│ ├── ISerializer.cs
│ ├── IStats.cs
│ ├── LogLevel.cs
│ ├── LogOptions.cs
│ ├── LogRollOptions.cs
│ ├── Logger.cs
│ ├── LoggerBase.cs
│ ├── MemoryDetail.cs
│ ├── MessageType.cs
│ ├── MethodSyncInfo.cs
│ ├── NamedPipes/
│ │ ├── DefaultNamedPipeServerStreamFactory.cs
│ │ ├── INamedPipeServerStreamFactory.cs
│ │ ├── NpChannel.cs
│ │ ├── NpChannelIdentifier.cs
│ │ ├── NpClient.cs
│ │ ├── NpEndPoint.cs
│ │ ├── NpHost.cs
│ │ ├── NpListener.cs
│ │ ├── NpProxy.cs
│ │ ├── PipeClientConnectionEventArgs.cs
│ │ ├── ReadFileToStream.cs
│ │ └── StreamString.cs
│ ├── NetExtensions.cs
│ ├── NullLogger.cs
│ ├── NullStats.cs
│ ├── ParameterTransferHelper.cs
│ ├── ParameterTypes.cs
│ ├── PooledDictionary.cs
│ ├── ProxyBuilder.cs
│ ├── ProxyFactory.cs
│ ├── SerializationValidator.cs
│ ├── ServiceInstance.cs
│ ├── ServiceSyncInfo.cs
│ ├── ServiceSyncInfoCacheKey.cs
│ ├── ServiceWire.csproj
│ ├── Stats.cs
│ ├── StatsBag.cs
│ ├── StreamingChannel.cs
│ ├── TcpIp/
│ │ ├── TcpChannel.cs
│ │ ├── TcpChannelIdentifier.cs
│ │ ├── TcpClient.cs
│ │ ├── TcpEndPoint.cs
│ │ ├── TcpHost.cs
│ │ ├── TcpProxy.cs
│ │ └── TcpZkEndPoint.cs
│ ├── ZeroKnowledge/
│ │ ├── IZkRepository.cs
│ │ ├── ZkBigInt.cs
│ │ ├── ZkCrypto.cs
│ │ ├── ZkExt.cs
│ │ ├── ZkPasswordHash.cs
│ │ ├── ZkProtocol.cs
│ │ ├── ZkSafePrimes.cs
│ │ └── ZkSession.cs
│ └── _license.txt
├── ServiceWire.sln
├── ServiceWireTestHostPlusClient/
│ ├── Program.cs
│ └── ServiceWireTestHostPlusClient.csproj
├── Tests/
│ ├── Integration/
│ │ ├── ServiceWireTestClient1/
│ │ │ ├── App.config
│ │ │ ├── Program.cs
│ │ │ └── ServiceWireTestClient1.csproj
│ │ ├── ServiceWireTestClient2/
│ │ │ ├── App.config
│ │ │ ├── Program.cs
│ │ │ └── ServiceWireTestClient2.csproj
│ │ └── ServiceWireTestHost/
│ │ ├── App.config
│ │ ├── Program.cs
│ │ └── ServiceWireTestHost.csproj
│ ├── ServiceWireTestCommon/
│ │ ├── ServiceWireTestCommon.csproj
│ │ └── TestContracts.cs
│ ├── Unit/
│ │ └── ServiceWireTests/
│ │ ├── AsyncTests.cs
│ │ ├── INetTester.cs
│ │ ├── InterceptionTests.cs
│ │ ├── NewtonsoftSerializer.cs
│ │ ├── NpTests.cs
│ │ ├── ParameterTransferHelperTests.cs
│ │ ├── ProtobufSerializer.cs
│ │ ├── SequentialCollection.cs
│ │ ├── ServiceWireTests.csproj
│ │ ├── TcpTests.cs
│ │ ├── TcpZkTests.cs
│ │ └── ZkProtocolTests.cs
│ └── testing_readme.txt
└── output.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
================================================
FILE: .github/workflows/build-and-test.yml
================================================
name: .NET Build and Tests in Linux and Windows
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
defaults:
run:
working-directory: src
jobs:
build_linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: Test
run: dotnet test --no-build --verbosity normal
build_windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: Test
run: dotnet test --no-build --verbosity normal
================================================
FILE: .gitignore
================================================
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.vspscc
.builds
*.dotCover
# NuGet Package Restore enabled
packages/
!packages/repositories.config
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
# Visual Studio profiler
*.psess
*.vsp
# ReSharper is a .NET coding add-in
_ReSharper*
# Installshield output folder
[Ee]xpress
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish
# Others
[Bb]in
[Oo]bj
sql
TestResults
*.Cache
ClientBin
stylecop.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
############
## Windows
############
# Windows image file caches
Thumbs.db
# Folder config file
Desktop.ini
#############
## Python
#############
*.py[co]
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
# Mac crap
.DS_Store
/src/.vs/config
/src/.vs/ProjectEvaluation
src/pack/lib/net35
src/pack/lib/net461
/src/.vs/ServiceWire
#.VS & VSCode
.vs/
.vscode/
/src/Benchmarks/ServiceWire.Benchmarks/BenchmarkDotNet.Artifacts
================================================
FILE: README.md
================================================
[](https://github.com/tylerjensen/ServiceWire/actions/workflows/build-and-test.yml)
[](https://ko-fi.com/tylerjensen)
ServiceWire
===========
### A Lightweight Services Library for .NET.
ServiceWire is a very fast and light weight services host and dynamic client library that simplifies the development and use of high performance remote procedure call (RPC) communication between .NET processes over Named Pipes or TCP/IP.
Find "how to use" examples in the tests code. [ServiceWire documentation][] is available on the wiki.
### Important
ServiceWire's dynamically generated proxy will NOT run as x86 on an x64 system. This ususally occurs when you use Visual Studio to create a console application with the default "prefer x86" in project properties selected. Just be sure to choose AnyCPU or the specific target (x86 or x64) so that you do not run 32bit in WOW on an x64 machine.
### Get It on Nuget
Get the [NuGet package here][].
### Using the library is easy.
1. Code your interface
2. Code your implementation
3. Host the implementation
4. Use dynamic proxy of your interface on the client side
### This unique library supports:
- TCP and NamedPipes protocols
- ByRef (out and ref) parameters (except for non-primitive value types)
- Dynamic client proxy generation from service interface
- Very fast serialization of most native types and arrays of those types
- Multiple service interface hosting on the same endpoint
- Aspect oriented interception with pre-, post- and exception handling cross cutting
- Hosting of single service implementation singleton on multiple endpoints and protocols
- Protocol, serialization and execution strategy extension
Portions of this library (dynamic proxy) are a derivative of RemotingLite by Frank Thomsen.
[NuGet package here]: http://www.nuget.org/packages/ServiceWire/
[RemotingLite by Frank Thomsen]: https://codeplexarchive.org/codeplex/project/RemotingLite
[ServiceWire documentation]: https://github.com/tylerjensen/ServiceWire/wiki
## History
### NamedPipeServerStreamFactory and Other Improvements 5.6.0
1. Contributed fix where accepting TCP clients synchronously may block new clients from being accepted until the terminating request is received on the synchronous client.
1. Contributed NamedPipeServerStreamFactory to allow greater level of permissions control in using named pipes.
1. Introducted injectable ILog and IStats across channels and clients with default NullLogger and NullStats, making InjectLoggerStats obsolete.
1. Code improvements for code consistency and eliminating outdated frameworks from tests and supporting projects.
1. Updated several dependencies in supporting projects.
1. Updated System.Text.Json to 9.0.0 to resolve known vulnerabilities in previous versions.
### Support for Enum by Ref 5.5.4
1. Contributed support for proper async exceptions.
### Support for Enum by Ref 5.5.3
1. Contributed support for Enum by ref parameters.
### Bug Fix for Important Edge Case 5.5.2
1. Contributed fix to case service on a host with same interface was called previously on a different host.
### Replaces BinaryFormatter with System.Text.Json 5.5.0
1. Replaces BinaryFormatter in DefaultSerializer with System.Text.Json. Improves performance and reduces allocations in serializing small object graphs which is the most common use case in any RPC library.
2. Fixes null value in string array bug #50.
3. See source for former DefaultSerializer in ServiceWire.Serializers in BinaryFormatterSerializer. Use that code as a custom injected serializer if this version breaks your serialization.
4. Using ServiceWire in an ASP.NET app no longer requires the use of the EnableUnsafeBinaryFormatterSerialization flag in your project file.
### Capture serialization error bug fix in 5.4.2
1. Single target of NetStandard 2.0 for a smaller NuGet package.
2. Fix to a NamedPipes performance issue.
3. Elimination of NET462 code differences.
### Capture serialization error bug fix in 5.4.1
1. In .NET 5+, the BinaryFormatter is marked obsolete and prohibited in ASP.NET apps.
2. This bug caused an end of stream error rather than capturing it properly. This version fixes that bug and exposes the limitation introduced in .NET 5+ on ASP.NET apps.
3. Using ServiceWire in an ASP.NET app is still possible but requires the use of the [EnableUnsafeBinaryFormatterSerialization](https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/5.0/binaryformatter-serialization-obsolete) flag in your project file. Use this carefully and be sure you understand the risks.
### ICompression added for injecting compression strategy in 5.4.0
1. Added ICompression for injecting custom compression into usage.
2. Added .NET 5.0 as target back in.
### AssemblyQualified names from user defined types in 5.3.6
1. Fix for AssemblyQualified names from user defined types.
### Multiple Framework Targets and void Return Types 5.3.5
1. Updated all projects to target .net462, .net48, netcoreapp3.1, and net6.0 only.
2. Corrected multiple targets for multiple OS in projects for those using Linux.
3. Updated NuGet package version.
### BugFix + Test cases + 48
1. Throwing the original error through an Intercept would fail for interface methods that have a void return type
2. Updated framework references from .net462 to .net48
### .NET Framework to .NET Core and Serializer Bug Fixes 5.3.4
1. Support for .NET Framework to .NET Core core parameter types to eliminate exceptions when a Framework client is talking to a Core host or vice versa.
2. Serializer injection bug fixed.
### .NET 4.62 added back in version 5.3.3
1. Added .NET Framework 4.62 build in package to prevent permissions issue in named pipes.
2. Fixed custom serializer issue.
3. .NET Standard 2.0 and 2.1 builds remain.
4. Resolved parallel Zk test issues.
Note: Use of async/await and Task<T> not recommended. Use of Task return type not supported. While the syntax of Task return type is supported, apparently it is not marked as Serializable. In fact async/await is not really supported. Under the covers the task type is stripped away over the wire and the method is executed on a worker thread on the server synchronously. If you think about it, you will understand that it's two separate processes, so the Task Parallel Library is not going to be able to manage the thread context across the processes. RPC is inherently synchronous but the handling of each request on the host is done on thread pools.
### .NET Standard 2.0 and 2.1 in version 5.3.2
1. Changed library build to only .NET Standard 2.0 and 2.1.
2. This breaks users of named pipes in .NET 4.6.2 -- DO NOT UPGRADE until we resolve that issue.
### Bug Fixes in version 5.3.1
1. Fixed bug related to complex type serialization that occurred when using output parameters.
### BREAKING CHANGES in version 5.3.0
1. Injectable serialization (see project library tests for examples).
2. Removes dependency on Newtonsoft.Json and uses BinaryFormatter for default serialization which means wire data classes must be marked [Serializable].
3. Internal classes are attributed to support protobuf-net serialization as well.
### Changes in version 5.2.0
1. Adds support for return types of Task and Task<T> to support async / await across the wire.
### Changes including some breaking changes in version 5.1.0
1. Dropped strong named assembly.
2. Support for NetCoreApp 2.0, 2.2 and .NET Framework 4.62. Dropped support for .NET 3.5.
3. Modified projects and NuGet package generation from Visual Studio 2017.
4. Dropped separate projects used to build different targets.
5. Converted test projects to XUnit with multiple targets to allow "dotnet test" run of all targets.
### Breaking Changes in version 4.0.1
1. Switched ServiceWire (and ServiceMq) to Newtonsoft.Json for serialization. Eliminates use of BinaryFormatter and its required Serializable attribute. Also eliminates ServiceStack.Text 3 dependency which has problems serializing structs.
2. Relaxed assembly version matching to allow additive changes without breaking the client or requiring an immediate client update.
3. Strong name added to allow the library to be used by strong named applications and libraries.
4. Added .NET 3.5 support to allow legacy applications to use the library. This adds a Framework specific dependency on TaskParallelLibrary 1.0.2856.0.
5. For the .NET 4.0 and 3.5 versions, changed to "Client Profile" for the target framework.
6. Removed dependency on System.Numerics in order to support .NET 3.5 and introduced ZkBigInt class taken from Scott Garland's BigInteger class. See license text for full attribution.
### Updated Benchmarks (12/5/2024) with latest contribution
NOTE: In this and previous runs of the benchmarks, .NET 8 is consistently 21% faster than .NET 6 when the benchmark differences are averaged.
```
BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4460/23H2/2023Update/SunValley3)
AMD Ryzen Threadripper PRO 5975WX 32-Cores, 1 CPU, 64 logical and 32 physical cores
.NET SDK 9.0.100
[Host] : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2
.NET 6.0 : .NET 6.0.36 (6.0.3624.51421), X64 RyuJIT AVX2
.NET 8.0 : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX2
| Type | Method | Job | Runtime | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|--------------------- |------------- |------------------- |------------------- |-------------:|-----------:|-----------:|------:|--------:|-------:|-------:|----------:|------------:|
| ConnectionBenchmarks | TcpConn | .NET 6.0 | .NET 6.0 | 15,400.91 us | 204.477 us | 191.267 us | 0.99 | 0.01 | - | - | 62874 B | 1.00 |
| ConnectionBenchmarks | TcpConn | .NET 8.0 | .NET 8.0 | 15,505.96 us | 76.118 us | 71.201 us | 1.00 | 0.01 | - | - | 62893 B | 1.00 |
| | | | | | | | | | | | | |
| NamedPipesBenchmarks | NpSim | .NET 6.0 | .NET 6.0 | 21.64 us | 0.132 us | 0.110 us | 1.37 | 0.04 | 0.0305 | - | 568 B | 0.89 |
| NamedPipesBenchmarks | NpSim | .NET 8.0 | .NET 8.0 | 15.86 us | 0.311 us | 0.415 us | 1.00 | 0.04 | 0.0305 | - | 640 B | 1.00 |
| | | | | | | | | | | | | |
| TcpBenchmarks | TcpSim | .NET 6.0 | .NET 6.0 | 27.60 us | 0.215 us | 0.201 us | 1.11 | 0.02 | 0.0305 | - | 568 B | 0.89 |
| TcpBenchmarks | TcpSim | .NET 8.0 | .NET 8.0 | 24.94 us | 0.484 us | 0.497 us | 1.00 | 0.03 | 0.0305 | - | 640 B | 1.00 |
| | | | | | | | | | | | | |
| ConnectionBenchmarks | NpConn | .NET 6.0 | .NET 6.0 | 235.46 us | 3.600 us | 3.192 us | 1.16 | 0.03 | 4.3945 | 0.4883 | 68798 B | 1.02 |
| ConnectionBenchmarks | NpConn | .NET 8.0 | .NET 8.0 | 203.27 us | 3.865 us | 3.969 us | 1.00 | 0.03 | 4.3945 | 0.4883 | 67196 B | 1.00 |
| | | | | | | | | | | | | |
| NamedPipesBenchmarks | NpSimJson | .NET 6.0 | .NET 6.0 | 21.44 us | 0.150 us | 0.125 us | 1.35 | 0.02 | 0.0305 | - | 568 B | 0.89 |
| NamedPipesBenchmarks | NpSimJson | .NET 8.0 | .NET 8.0 | 15.94 us | 0.306 us | 0.286 us | 1.00 | 0.02 | 0.0305 | - | 640 B | 1.00 |
| | | | | | | | | | | | | |
| TcpBenchmarks | TcpSimJson | .NET 6.0 | .NET 6.0 | 27.80 us | 0.550 us | 0.564 us | 1.14 | 0.03 | 0.0305 | - | 568 B | 0.89 |
| TcpBenchmarks | TcpSimJson | .NET 8.0 | .NET 8.0 | 24.44 us | 0.299 us | 0.280 us | 1.00 | 0.02 | 0.0305 | - | 640 B | 1.00 |
| | | | | | | | | | | | | |
| NamedPipesBenchmarks | NpRg | .NET 6.0 | .NET 6.0 | 61.25 us | 0.710 us | 0.554 us | 1.38 | 0.03 | 0.8545 | - | 15416 B | 1.05 |
| NamedPipesBenchmarks | NpRg | .NET 8.0 | .NET 8.0 | 44.48 us | 0.800 us | 1.122 us | 1.00 | 0.03 | 0.9766 | - | 14737 B | 1.00 |
| | | | | | | | | | | | | |
| TcpBenchmarks | TcpRg | .NET 6.0 | .NET 6.0 | 72.16 us | 1.325 us | 1.174 us | 1.37 | 0.03 | 0.8545 | - | 15416 B | 1.05 |
| TcpBenchmarks | TcpRg | .NET 8.0 | .NET 8.0 | 52.70 us | 0.834 us | 0.739 us | 1.00 | 0.02 | 0.7324 | - | 14737 B | 1.00 |
| | | | | | | | | | | | | |
| NamedPipesBenchmarks | NpRgJson | .NET 6.0 | .NET 6.0 | 68.63 us | 0.631 us | 0.590 us | 1.39 | 0.04 | 1.7090 | - | 27193 B | 1.09 |
| NamedPipesBenchmarks | NpRgJson | .NET 8.0 | .NET 8.0 | 49.40 us | 0.979 us | 1.239 us | 1.00 | 0.03 | 1.4648 | - | 24881 B | 1.00 |
| | | | | | | | | | | | | |
| TcpBenchmarks | TcpRgJson | .NET 6.0 | .NET 6.0 | 73.17 us | 1.181 us | 0.986 us | 1.38 | 0.03 | 0.8545 | - | 15416 B | 1.05 |
| TcpBenchmarks | TcpRgJson | .NET 8.0 | .NET 8.0 | 53.03 us | 0.824 us | 0.771 us | 1.00 | 0.02 | 0.7324 | - | 14737 B | 1.00 |
| | | | | | | | | | | | | |
| NamedPipesBenchmarks | NpCxOut | .NET 6.0 | .NET 6.0 | 54.18 us | 0.444 us | 0.416 us | 1.25 | 0.02 | 0.3662 | - | 6928 B | 0.86 |
| NamedPipesBenchmarks | NpCxOut | .NET 8.0 | .NET 8.0 | 43.36 us | 0.608 us | 0.569 us | 1.00 | 0.02 | 0.3662 | - | 8064 B | 1.00 |
| | | | | | | | | | | | | |
| TcpBenchmarks | TcpCxOut | .NET 6.0 | .NET 6.0 | 64.20 us | 1.172 us | 1.565 us | 1.36 | 0.04 | 0.3662 | - | 6929 B | 0.86 |
| TcpBenchmarks | TcpCxOut | .NET 8.0 | .NET 8.0 | 47.21 us | 0.782 us | 0.732 us | 1.00 | 0.02 | 0.3662 | - | 8064 B | 1.00 |
| | | | | | | | | | | | | |
| NamedPipesBenchmarks | NpCxOutJson | .NET 6.0 | .NET 6.0 | 58.34 us | 0.904 us | 0.801 us | 1.34 | 0.02 | 0.6104 | - | 10856 B | 0.91 |
| NamedPipesBenchmarks | NpCxOutJson | .NET 8.0 | .NET 8.0 | 43.61 us | 0.655 us | 0.581 us | 1.00 | 0.02 | 0.7324 | - | 11888 B | 1.00 |
| | | | | | | | | | | | | |
| TcpBenchmarks | TcpCxOutJson | .NET 6.0 | .NET 6.0 | 63.73 us | 1.143 us | 1.069 us | 1.34 | 0.03 | 0.3662 | - | 6929 B | 0.86 |
| TcpBenchmarks | TcpCxOutJson | .NET 8.0 | .NET 8.0 | 47.49 us | 0.641 us | 0.600 us | 1.00 | 0.02 | 0.3662 | - | 8064 B | 1.00 |
```
================================================
FILE: src/Benchmarks/ServiceWire.Benchmarks/ConnectionBenchmarks.cs
================================================
using System;
using ServiceWire.NamedPipes;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using ServiceWire.TcpIp;
using System.Net;
namespace ServiceWire.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net80, baseline: true)]
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net48)]
[MemoryDiagnoser]
[HtmlExporter]
public class ConnectionBenchmarks
{
private INetTester _tester;
private Random _rnd;
private readonly string PipeName = "ServiceWireBenchmarkHost";
private IPAddress _ipAddress;
private const int Port = 8084;
private IPEndPoint CreateTcpEndPoint(int portOffset)
{
return new IPEndPoint(_ipAddress, Port + portOffset);
}
private NpEndPoint CreateNpEndPoint(string offset)
{
return new NpEndPoint(PipeName + offset);
}
public ConnectionBenchmarks()
{
_rnd = new Random();
_tester = new NetTester();
_ipAddress = IPAddress.Parse("127.0.0.1");
}
[Benchmark]
public void TcpConn()
{
using (var tcpHost = new TcpHost(CreateTcpEndPoint(0)))
{
tcpHost.AddService<INetTester>(_tester);
tcpHost.Open();
using (var tcpClient = new TcpClient<INetTester>(CreateTcpEndPoint(0)))
{
var a = _rnd.Next(0, 100);
var b = _rnd.Next(0, 100);
var result = tcpClient.Proxy.Min(a, b);
}
}
}
[Benchmark]
public void NpConn()
{
using (var npHost = new NpHost(PipeName))
{
npHost.AddService<INetTester>(_tester);
npHost.Open();
using (var npClient = new NpClient<INetTester>(CreateNpEndPoint(string.Empty)))
{
var a = _rnd.Next(0, 100);
var b = _rnd.Next(0, 100);
var result = npClient.Proxy.Min(a, b);
}
}
}
}
}
================================================
FILE: src/Benchmarks/ServiceWire.Benchmarks/INetTester.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ServiceWire.Benchmarks
{
public interface INetTester
{
int Min(int a, int b);
Dictionary<int, int> Range(int start, int count);
TestResponse Get(Guid id, string label, double weight, out int quantity);
Task<int> CalculateAsync(int a, int b);
}
[Serializable]
public struct TestResponse
{
public Guid Id { get; set; }
public string Label { get; set; }
public long Quantity { get; set; }
public IList<string> Values { get; set; }
}
public class NetTester : INetTester
{
public int Min(int a, int b)
{
return Math.Min(a, b);
}
public Dictionary<int, int> Range(int start, int count)
{
return Enumerable.Range(start, count).ToDictionary(key => key, el => el);
}
public Task<int> CalculateAsync(int a, int b)
{
return Task.FromResult(a + b);
}
public TestResponse Get(Guid id, string label, double weight, out int quantity)
{
quantity = 44;
return new TestResponse { Id = id, Label = "MyLabel", Quantity = quantity, Values = new List<string> { "one", "two", "three", "four" } };
}
}
}
================================================
FILE: src/Benchmarks/ServiceWire.Benchmarks/NamedPipesBenchmarks.cs
================================================
using System;
using ServiceWire.NamedPipes;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
namespace ServiceWire.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net80, baseline: true)]
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net48)]
[MemoryDiagnoser]
[HtmlExporter]
public class NamedPipesBenchmarks
{
private INetTester _tester;
private NpHost _nphost;
private NpHost _nphostJson;
private NpClient<INetTester> _npClient = null;
private NpClient<INetTester> _npClientJson = null;
private Random _rnd;
private readonly string PipeName = "ServiceWireBenchmarkHost";
private NpEndPoint CreateNpEndPoint(string offset)
{
return new NpEndPoint(PipeName + offset);
}
public NamedPipesBenchmarks()
{
_rnd = new Random();
_tester = new NetTester();
_nphost = new NpHost(PipeName);
_nphost.AddService<INetTester>(_tester);
_nphost.Open();
_nphostJson = new NpHost(PipeName + "Json", serializer: new NewtonsoftSerializer());
_nphostJson.AddService<INetTester>(_tester);
_nphostJson.Open();
}
[GlobalSetup]
public void GlobalSetup()
{
_npClient = new NpClient<INetTester>(CreateNpEndPoint(string.Empty));
_npClientJson = new NpClient<INetTester>(CreateNpEndPoint("Json"), new NewtonsoftSerializer());
}
[GlobalCleanup]
public void GlobalCleanup()
{
_npClient.Dispose();
_npClientJson.Dispose();
_nphost.Close();
_nphostJson.Close();
}
[Benchmark]
public void NpSim()
{
var a = _rnd.Next(0, 100);
var b = _rnd.Next(0, 100);
var result = _npClient.Proxy.Min(a, b);
}
[Benchmark]
public void NpSimJson()
{
var a = _rnd.Next(0, 100);
var b = _rnd.Next(0, 100);
var result = _npClientJson.Proxy.Min(a, b);
}
[Benchmark]
public void NpRg()
{
var result = _npClient.Proxy.Range(0, 50);
for (var i = 0; i < 50; i++)
{
int temp;
result.TryGetValue(i, out temp);
}
}
[Benchmark]
public void NpRgJson()
{
var result = _npClientJson.Proxy.Range(0, 50);
for (var i = 0; i < 50; i++)
{
int temp;
result.TryGetValue(i, out temp);
}
}
[Benchmark]
public void NpCxOut()
{
int quantity = 0;
var result = _npClient.Proxy.Get(Guid.NewGuid(), "SomeLabel", 45.65, out quantity);
}
[Benchmark]
public void NpCxOutJson()
{
int quantity = 0;
var result = _npClientJson.Proxy.Get(Guid.NewGuid(), "SomeLabel", 45.65, out quantity);
}
}
}
================================================
FILE: src/Benchmarks/ServiceWire.Benchmarks/NewtonSoftSerializer.cs
================================================
using System;
using System.Text;
using Newtonsoft.Json;
namespace ServiceWire.Benchmarks
{
public class NewtonsoftSerializer : ISerializer
{
private JsonSerializerSettings settings = new JsonSerializerSettings
{
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};
public T Deserialize<T>(byte[] bytes)
{
if (null == bytes || bytes.Length == 0) return default(T);
var json = Encoding.UTF8.GetString(bytes);
return JsonConvert.DeserializeObject<T>(json, settings);
}
public object Deserialize(byte[] bytes, string typeConfigName)
{
if (null == typeConfigName) throw new ArgumentNullException(nameof(typeConfigName));
var type = typeConfigName.ToType();
if (null == typeConfigName || null == bytes || bytes.Length == 0) return type.GetDefault();
var json = Encoding.UTF8.GetString(bytes);
return JsonConvert.DeserializeObject(json, type, settings);
}
public byte[] Serialize<T>(T obj)
{
if (null == obj) return null;
var json = JsonConvert.SerializeObject(obj, settings);
return Encoding.UTF8.GetBytes(json);
}
public byte[] Serialize(object obj, string typeConfigName)
{
if (null == obj) return null;
var type = typeConfigName.ToType();
var json = JsonConvert.SerializeObject(obj, type, settings);
return Encoding.UTF8.GetBytes(json);
}
}
}
================================================
FILE: src/Benchmarks/ServiceWire.Benchmarks/Program.cs
================================================
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Running;
namespace ServiceWire.Benchmarks
{
public class Program
{
public static void Main(string[] args)
{
// These can be helpful if you're just trying to work on a single benchmark
//BenchmarkRunner.Run<ConnectionBenchmarks>();
//BenchmarkRunner.Run<NamedPipesBenchmarks>();
//BenchmarkRunner.Run<TcpBenchmarks>();
var switcher = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly);
// Run with command line args if provided
if (args.Length > 0)
{
switcher.Run(args);
return;
}
// Otherwise run them all and combine the results into a single report (command line, HTML)
var summary = switcher.RunAllJoined();
// Launching the html report in the browser, makes it nice and easy to see the results
string htmlReportPath = System.IO.Path.Combine(summary.ResultsDirectoryPath, $"{summary.Title}-report.html");
OpenUrl(htmlReportPath);
}
private static void OpenUrl(string url)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
url = url.Replace("&", "^&");
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// Detects to see if the user is running in a "desktop environment"/GUI, or if they are running in a terminal session.
// Won't be able to launch a web browser without a GUI
// https://en.wikipedia.org/wiki/Desktop_environment
var currDesktopEnvironment = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP");
if (String.IsNullOrEmpty(currDesktopEnvironment))
{
return;
}
Process.Start("xdg-open", url);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Process.Start("open", url);
}
}
}
}
================================================
FILE: src/Benchmarks/ServiceWire.Benchmarks/ServiceWire.Benchmarks.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;net6.0;net48</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0'">
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="protobuf-net" Version="3.2.45" />
<PackageReference Include="System.Private.Uri" Version="4.3.2" />
<PackageReference Include="System.Reflection.Metadata" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ServiceWire\ServiceWire.csproj" />
</ItemGroup>
</Project>
================================================
FILE: src/Benchmarks/ServiceWire.Benchmarks/TcpBenchmarks.cs
================================================
using System;
using ServiceWire.TcpIp;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using System.Net;
namespace ServiceWire.Benchmarks
{
[SimpleJob(RuntimeMoniker.Net80, baseline: true)]
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net48)]
[MemoryDiagnoser]
[HtmlExporter]
public class TcpBenchmarks
{
private INetTester _tester;
private Random _rnd;
private TcpHost _tcphost;
private TcpHost _tcphostJson;
private TcpClient<INetTester> _tcpClient;
private TcpClient<INetTester> _tcpClientJson;
private IPAddress _ipAddress;
private const int Port = 8084;
private IPEndPoint CreateTcpEndPoint(int portOffset)
{
return new IPEndPoint(_ipAddress, Port + portOffset);
}
public TcpBenchmarks()
{
_rnd = new Random();
_tester = new NetTester();
_ipAddress = IPAddress.Parse("127.0.0.1");
_tcphost = new TcpHost(CreateTcpEndPoint(0));
_tcphost.AddService<INetTester>(_tester);
_tcphost.Open();
_tcphostJson = new TcpHost(CreateTcpEndPoint(1));
_tcphostJson.AddService<INetTester>(_tester);
_tcphostJson.Open();
}
[GlobalSetup]
public void GlobalSetup()
{
_tcpClient = new TcpClient<INetTester>(CreateTcpEndPoint(0));
_tcpClientJson = new TcpClient<INetTester>(CreateTcpEndPoint(1));
}
[GlobalCleanup]
public void GlobalCleanup()
{
_tcpClient.Dispose();
_tcpClientJson.Dispose();
_tcphost.Close();
_tcphostJson.Close();
}
[Benchmark]
public void TcpSim()
{
var a = _rnd.Next(0, 100);
var b = _rnd.Next(0, 100);
var result = _tcpClient.Proxy.Min(a, b);
}
[Benchmark]
public void TcpSimJson()
{
var a = _rnd.Next(0, 100);
var b = _rnd.Next(0, 100);
var result = _tcpClientJson.Proxy.Min(a, b);
}
[Benchmark]
public void TcpRg()
{
var result = _tcpClient.Proxy.Range(0, 50);
for (var i = 0; i < 50; i++)
{
int temp;
result.TryGetValue(i, out temp);
}
}
[Benchmark]
public void TcpRgJson()
{
var result = _tcpClientJson.Proxy.Range(0, 50);
for (var i = 0; i < 50; i++)
{
int temp;
result.TryGetValue(i, out temp);
}
}
[Benchmark]
public void TcpCxOut()
{
int quantity = 0;
var result = _tcpClient.Proxy.Get(Guid.NewGuid(), "SomeLabel", 45.65, out quantity);
}
[Benchmark]
public void TcpCxOutJson()
{
int quantity = 0;
var result = _tcpClientJson.Proxy.Get(Guid.NewGuid(), "SomeLabel", 45.65, out quantity);
}
}
}
================================================
FILE: src/Demo/DemoClient/App.config
================================================
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
</configuration>
================================================
FILE: src/Demo/DemoClient/DemoClient.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT' ">
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<TargetFrameworks>net6.0;net8.0;net48</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0'">
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="9.0.0" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="9.0.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.0" />
<PackageReference Include="System.Text.Json" Version="9.0.0" />
<PackageReference Include="System.Private.Uri" Version="4.3.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ServiceWire\ServiceWire.csproj" />
<ProjectReference Include="..\DemoCommon\DemoCommon.csproj" />
</ItemGroup>
</Project>
================================================
FILE: src/Demo/DemoClient/Program.cs
================================================
using DemoCommon;
using ServiceWire;
using ServiceWire.TcpIp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
namespace DemoClient
{
class Program
{
private static async Task Main(string[] args)
{
var logger = new Logger(logLevel: LogLevel.Debug);
var stats = new Stats();
var addr = new[] { "127.0.0.1", "8098" }; //defaults
if (null != args && args.Length > 0)
{
var parts = args[0].Split(':');
if (parts.Length > 1) addr[1] = parts[1];
addr[0] = parts[0];
}
var ip = addr[0];
var port = Convert.ToInt32(addr[1]);
//var zkEndpoint = new TcpZkEndPoint("username", "password",
// new IPEndPoint(IPAddress.Parse(ip), port), connectTimeOutMs: 250000);
var zkEndpoint = new IPEndPoint(IPAddress.Parse(ip), port);
Console.WriteLine("Iteration 1");
await RunTest(zkEndpoint, ip, logger, stats);
Console.WriteLine("Iteration 2");
await RunTest(zkEndpoint, ip, logger, stats);
Console.ReadLine();
}
private static async Task RunTest(IPEndPoint zkEndpoint, string ip, Logger logger, Stats stats)
{
var sw = Stopwatch.StartNew();
using (var client = new TcpClient<ITest>(zkEndpoint))
{
client.InjectLoggerStats(logger, stats);
await client.Proxy.SetAsync(1);
int value = await client.Proxy.GetAsync();
}
using (var client = new TcpClient<IDataContract>(zkEndpoint))
{
client.InjectLoggerStats(logger, stats);
decimal abc = client.Proxy.GetDecimal(4.5m);
bool result = client.Proxy.OutDecimal(abc);
}
using (var client = new TcpClient<IComplexDataContract>(zkEndpoint))
{
client.InjectLoggerStats(logger, stats);
var id = client.Proxy.GetId("test1", 3.314, 42, DateTime.Now);
long q = 3;
var response = client.Proxy.Get(id, "mirror", 4.123, out q);
var list = client.Proxy.GetItems(id);
}
using (var client = new TcpClient<IIPCBridge>(zkEndpoint))
{
client.InjectLoggerStats(logger, stats);
var response = client.Proxy.GetData();
Console.WriteLine(response.First());
}
Console.WriteLine("elapsed ms: {0}", sw.ElapsedMilliseconds);
}
private static async Task RunTest(TcpZkEndPoint zkEndpoint, string ip, Logger logger, Stats stats)
{
var sw = Stopwatch.StartNew();
using (var client = new TcpClient<ITest>(zkEndpoint))
{
client.InjectLoggerStats(logger, stats);
await client.Proxy.SetAsync(1);
int value = await client.Proxy.GetAsync();
}
using (var client = new TcpClient<IDataContract>(zkEndpoint))
{
client.InjectLoggerStats(logger, stats);
decimal abc = client.Proxy.GetDecimal(4.5m);
bool result = client.Proxy.OutDecimal(abc);
}
using (var client = new TcpClient<IComplexDataContract>(zkEndpoint))
{
client.InjectLoggerStats(logger, stats);
var id = client.Proxy.GetId("test1", 3.314, 42, DateTime.Now);
long q = 3;
var response = client.Proxy.Get(id, "mirror", 4.123, out q);
var list = client.Proxy.GetItems(id);
}
using (var client = new TcpClient<IIPCBridge>(zkEndpoint))
{
client.InjectLoggerStats(logger, stats);
var response = client.Proxy.GetData();
Console.WriteLine(response.First());
}
Console.WriteLine("elapsed ms: {0}", sw.ElapsedMilliseconds);
}
}
}
================================================
FILE: src/Demo/DemoCommon/Contracts.cs
================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace DemoCommon
{
public interface ITest
{
Task SetAsync(int a);
Task<int> GetAsync();
}
public interface IDataContract
{
decimal GetDecimal(decimal input);
bool OutDecimal(decimal val);
}
public interface IIPCBridge
{
List<float> GetData();
}
public interface IComplexDataContract
{
Guid GetId(string source, double weight, int quantity, DateTime dt);
ComplexResponse Get(Guid id, string label, double weight, out long quantity);
long TestLong(out long id1, out long id2);
List<string> GetItems(Guid id);
}
[Serializable]
public struct ComplexResponse
{
public Guid Id { get; set; }
public string Label { get; set; }
public long Quantity { get; set; }
}
}
================================================
FILE: src/Demo/DemoCommon/DemoCommon.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT' ">
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<TargetFrameworks>net6.0;net8.0;net48</TargetFrameworks>
</PropertyGroup>
</Project>
================================================
FILE: src/Demo/DemoHost/App.config
================================================
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
</configuration>
================================================
FILE: src/Demo/DemoHost/DemoHost.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT' ">
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<TargetFrameworks>net6.0;net8.0;net48</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0'">
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="9.0.0" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="9.0.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.0" />
<PackageReference Include="System.Text.Json" Version="9.0.0" />
<PackageReference Include="System.Private.Uri" Version="4.3.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ServiceWire\ServiceWire.csproj" />
<ProjectReference Include="..\DemoCommon\DemoCommon.csproj" />
</ItemGroup>
</Project>
================================================
FILE: src/Demo/DemoHost/Program.cs
================================================
using DemoCommon;
using ServiceWire;
using ServiceWire.TcpIp;
using ServiceWire.ZeroKnowledge;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace DemoHost
{
class Program
{
static void Main(string[] args)
{
var logger = new Logger(logLevel: LogLevel.Debug);
var stats = new Stats();
var addr = new[] { "127.0.0.1", "8098" }; //defaults
if (null != args && args.Length > 0)
{
var parts = args[0].Split(':');
if (parts.Length > 1) addr[1] = parts[1];
addr[0] = parts[0];
}
var ip = addr[0];
var port = Convert.ToInt32(addr[1]);
var ipEndpoint = new IPEndPoint(IPAddress.Any, port);
var useCompression = false;
var compressionThreshold = 131072; //128KB
var zkRepository = new DemoZkRepository();
//var tcphost = new TcpHost(ipEndpoint, logger, stats, zkRepository);
var tcphost = new TcpHost(ipEndpoint, logger, stats);
tcphost.UseCompression = useCompression;
tcphost.CompressionThreshold = compressionThreshold;
var simpleContract = new DataContractImpl();
tcphost.AddService<IDataContract>(simpleContract);
var complexContract = new ComplexDataContractImpl();
tcphost.AddService<IComplexDataContract>(complexContract);
var bridge = new IPCBridge();
tcphost.AddService<IIPCBridge>(bridge);
var test = new Test();
tcphost.AddService<ITest>(test);
tcphost.Open();
Console.WriteLine("Press Enter to stop the dual host test.");
Console.ReadLine();
tcphost.Close();
Console.WriteLine("Press Enter to quit.");
Console.ReadLine();
}
}
public class IPCBridge : IIPCBridge
{
public List<float> GetData()
{
List<float> list = new List<float>();
list.Add(99.625F);
return list;
}
}
public class Test : ITest
{
public Task SetAsync(int a)
{
return Task.CompletedTask;
}
public Task<int> GetAsync()
{
return Task.FromResult(1);
}
}
public class DataContractImpl : IDataContract
{
public decimal GetDecimal(decimal input)
{
return input += 456.44m;
}
public bool OutDecimal(decimal val)
{
val = 45.66m;
return true;
}
}
public class ComplexDataContractImpl : IComplexDataContract
{
public Guid GetId(string source, double weight, int quantity, DateTime dt)
{
return Guid.NewGuid();
}
public ComplexResponse Get(Guid id, string label, double weight, out long quantity)
{
quantity = 42;
return new ComplexResponse { Id = id, Label = "Hello, world.", Quantity = quantity };
}
public List<string> GetItems(Guid id)
{
var list = new List<string>();
list.Add("42");
list.Add(id.ToString());
list.Add("Test");
return list;
}
public long TestLong(out long id1, out long id2)
{
id1 = 23;
id2 = 24;
return 25;
}
}
public class DemoZkRepository : IZkRepository
{
private string password = "password";
private ZkProtocol _protocol = new ZkProtocol();
private ZkPasswordHash _hash = null;
public ZkPasswordHash GetPasswordHashSet(string username)
{
if (_hash == null) _hash = _protocol.HashCredentials(username, password);
return _hash;
}
}
}
================================================
FILE: src/License.txt
================================================
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
COPYRIGHT NOTICES AND OPEN SOURCE LICENSES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Title: ServiceWire
Description: Very fast and light weight services host and dynamic client
library that simplifies the development and use of high
performance remote procedure call (RPC) communication between
.NET processes over Named Pipes or TCP/IP.
Copyright (C) Tyler Jensen
Author: Tyler Jensen
Source: https://github.com/tylerjensen/ServiceWire
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
This notice, including the DERIVITIVE WORK NOTCE below, must be included in
compiled and source form of this work whenever distributed.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NAME CHANGE NOTICE
The code in this work was originally published under the name DuoVia.Net. This
work is a continuation of that project under the same copyright holder and author.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
DERIVATIVE WORK NOTICE
Some of the source code in this work is derived from RemotingLite version 1.2.5
available at http://remotinglite.codeplex.com. The author of RemotingLite
provides no endorsement, explicitly or implied, of this work.
The original source is published under the following license terms:
New BSD License (BSD)
Copyright (c) 2008, Frank Thomsen
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Sector 0 nor the names of its contributors may be used
to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
In addition, the following license information was part of the original source
files but has been moved here for code brevity:
RemotingLite
------
A light framework for making remote method invocations using TCP/IP. It is based loosely on
Windows Communication Foundation, and is meant to provide programmers with the same API
regardless of whether they write software for the Microsoft .NET platform or the Mono .NET
platform.
Consult the documentation and example applications for information about how to use this API.
Author : Frank Thomsen
http : http://sector0.dk
Concact : http://sector0.dk/?q=contact
Information : http://sector0.dk/?q=node/27
Licence : Free. If you use this, please let me know.
Please feel free to contact me with ideas, bugs or improvements.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
DERIVATIVE WORK NOTICE
This work includes a private branch of Scott Garland's BigInteger renamed as ZkBigInt.
The MIT License (MIT)
Copyright (c) 2007 Scott Garland
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: src/Serializers/ServiceWire.Serializers/BinaryFormatterSerializer.cs
================================================
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace ServiceWire.Serializers
{
public class BinaryFormatterSerializer : ISerializer
{
private readonly IFormatter _formatter = new BinaryFormatter();
public byte[] Serialize<T>(T obj)
{
if (null == obj) return null;
using (var ms = new MemoryStream())
{
_formatter.Serialize(ms, obj);
return ms.ToArray();
}
}
public byte[] Serialize(object obj, string typeConfigName)
{
if (null == obj) return null;
using (var ms = new MemoryStream())
{
var type = typeConfigName.ToType();
var objT = Convert.ChangeType(obj, type);
_formatter.Serialize(ms, objT);
return ms.ToArray();
}
}
public T Deserialize<T>(byte[] bytes)
{
if (null == bytes || bytes.Length == 0) return default(T);
using (var ms = new MemoryStream(bytes))
{
return (T)_formatter.Deserialize(ms);
}
}
public object Deserialize(byte[] bytes, string typeConfigName)
{
if (null == typeConfigName) throw new ArgumentNullException(nameof(typeConfigName));
var type = typeConfigName.ToType();
if (null == typeConfigName || null == bytes || bytes.Length == 0) return type.GetDefault();
using (var ms = new MemoryStream(bytes))
{
var obj = _formatter.Deserialize(ms);
return Convert.ChangeType(obj, type);
}
}
}
}
================================================
FILE: src/Serializers/ServiceWire.Serializers/ServiceWire.Serializers.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ServiceWire" Version="5.5.4" />
<PackageReference Include="System.Text.Json" Version="9.0.0" />
</ItemGroup>
</Project>
================================================
FILE: src/ServiceWire/Aspects/CrossCuttingConcerns.cs
================================================
using System;
namespace ServiceWire.Aspects
{
public class CrossCuttingConcerns
{
/// <summary>
/// Takes instanceId, methodName and method parameters as object array.
/// </summary>
public Action<int, string, object[]> PreInvoke { get; set; }
/// <summary>
/// Takes instanceId, methodName, method parameters as object array, and exception thrown. Return true to call throw and raise exception.
/// </summary>
public Func<int, string, object[], Exception, bool> ExceptionHandler { get; set; }
/// <summary>
/// Takes instanceId, methodName and object array returned by execution of method.
/// </summary>
public Action<int, string, object[]> PostInvoke { get; set; }
}
}
================================================
FILE: src/ServiceWire/Aspects/InterceptChannel.cs
================================================
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;
namespace ServiceWire.Aspects
{
public class InterceptChannel : Channel
{
private InterceptPoint _interceptPoint;
private ServiceInstance _serviceInstance;
public InterceptPoint InterceptPoint { get { return _interceptPoint; } }
public InterceptChannel(Type interceptedType, InterceptPoint interceptPoint, ISerializer serializer, ICompressor compressor,
ILog logger = null, IStats stats = null)
: base(serializer, compressor, logger, stats)
{
_serviceType = interceptedType;
_interceptPoint = interceptPoint;
CreateMethodMap();
}
protected override void SyncInterface(Type interceptedType,
string username = null, string password = null)
{
//do nothing in this channel
}
/// <summary>
/// Loads all methods from interfaces and assigns an identifier
/// to each. These are later synchronized with the client.
/// </summary>
private void CreateMethodMap()
{
_serviceInstance = new ServiceInstance()
{
KeyIndex = 0, //only one per intercepted interface
InterfaceType = _serviceType,
InterfaceMethods = new ConcurrentDictionary<int, MethodInfo>(),
MethodParametersByRef = new ConcurrentDictionary<int, bool[]>(),
SingletonInstance = _interceptPoint.Target
};
var currentMethodIdent = 0;
if (_serviceType.IsInterface)
{
var methodInfos = _serviceType.GetMethods();
foreach (var mi in methodInfos)
{
_serviceInstance.InterfaceMethods.TryAdd(currentMethodIdent, mi);
var parameterInfos = mi.GetParameters();
var isByRef = new bool[parameterInfos.Length];
for (int i = 0; i < isByRef.Length; i++)
isByRef[i] = parameterInfos[i].ParameterType.IsByRef;
_serviceInstance.MethodParametersByRef.TryAdd(currentMethodIdent, isByRef);
currentMethodIdent++;
}
}
var interfaces = _serviceType.GetInterfaces();
foreach (var interfaceType in interfaces)
{
var methodInfos = interfaceType.GetMethods();
foreach (var mi in methodInfos)
{
_serviceInstance.InterfaceMethods.TryAdd(currentMethodIdent, mi);
var parameterInfos = mi.GetParameters();
var isByRef = new bool[parameterInfos.Length];
for (int i = 0; i < isByRef.Length; i++)
isByRef[i] = parameterInfos[i].ParameterType.IsByRef;
_serviceInstance.MethodParametersByRef.TryAdd(currentMethodIdent, isByRef);
currentMethodIdent++;
}
}
//Create a list of sync infos from the dictionary
var syncSyncInfos = new List<MethodSyncInfo>();
foreach (var kvp in _serviceInstance.InterfaceMethods)
{
var parameters = kvp.Value.GetParameters();
var parameterTypes = new string[parameters.Length];
for (var i = 0; i < parameters.Length; i++)
parameterTypes[i] = parameters[i].ParameterType.ToConfigName();
syncSyncInfos.Add(new MethodSyncInfo
{
MethodIdent = kvp.Key,
MethodName = kvp.Value.Name,
MethodReturnType = kvp.Value.ReturnType.ToConfigName(),
ParameterTypes = parameterTypes
});
}
var serviceSyncInfo = new ServiceSyncInfo
{
ServiceKeyIndex = 0,
CompressionThreshold = 131072,
UseCompression = false,
MethodInfos = syncSyncInfos.ToArray()
};
_serviceInstance.ServiceSyncInfo = serviceSyncInfo;
}
protected override object[] InvokeMethod(string metaData, params object[] parameters)
{
object[] returnParameters = null;
Type returnType = null;
try
{
var mdata = metaData.Split('|');
var ident = -1;
for (int index = 0; index < _serviceInstance.ServiceSyncInfo.MethodInfos.Length; index++)
{
var si = _serviceInstance.ServiceSyncInfo.MethodInfos[index];
//first of all the method names must match
if (si.MethodName == mdata[0])
{
//second of all the parameter types and -count must match
if (mdata.Length - 1 == si.ParameterTypes.Length)
{
var matchingParameterTypes = true;
for (int i = 0; i < si.ParameterTypes.Length; i++)
{
if (!mdata[i + 1].Equals(si.ParameterTypes[i]))
{
matchingParameterTypes = false;
break;
}
}
if (matchingParameterTypes)
{
ident = si.MethodIdent;
break;
}
}
}
}
if (ident < 0)
throw new Exception(string.Format("Cannot match method '{0}' to its implementation.", mdata[0]));
if (_serviceInstance.InterfaceMethods.ContainsKey(ident))
{
MethodInfo method;
_serviceInstance.InterfaceMethods.TryGetValue(ident, out method);
bool[] isByRef;
_serviceInstance.MethodParametersByRef.TryGetValue(ident, out isByRef);
returnType = (null == method) ? null : method.ReturnType;
//invoke the method
try
{
if (null != _interceptPoint.Cut && null != _interceptPoint.Cut.PreInvoke)
{
_interceptPoint.Cut.PreInvoke(_interceptPoint.Id, mdata[0], parameters);
}
object returnValue = method.Invoke(_serviceInstance.SingletonInstance, parameters);
//the result to the client is the return value (null if void) and the input parameters
returnParameters = new object[1 + parameters.Length];
returnParameters[0] = returnValue;
for (int i = 0; i < parameters.Length; i++)
returnParameters[i + 1] = isByRef[i] ? parameters[i] : null;
}
catch (Exception ex)
{
Exception exceptionOfConcern = ex;
if (exceptionOfConcern is TargetInvocationException && null != exceptionOfConcern.InnerException)
{
exceptionOfConcern = exceptionOfConcern.InnerException;
}
bool shouldThrow = true;
if (null != _interceptPoint.Cut && null != _interceptPoint.Cut.ExceptionHandler)
{
shouldThrow = _interceptPoint.Cut.ExceptionHandler(_interceptPoint.Id, mdata[0], parameters,
exceptionOfConcern);
}
if (shouldThrow)
{
returnParameters = new object[] { exceptionOfConcern };
throw exceptionOfConcern;
} else
{
returnParameters = new object[]
{
returnType == typeof(void)? null: returnType.GetDefault()
};
}
}
finally
{
if (null != _interceptPoint.Cut && null != _interceptPoint.Cut.PostInvoke)
{
_interceptPoint.Cut.PostInvoke(_interceptPoint.Id, mdata[0], returnParameters);
}
}
return returnParameters;
}
throw new Exception(string.Format("Cannot match method '{0}' to its implementation.", mdata[0]));
}
catch
{
//log?
throw;
}
}
protected override void Dispose(bool disposing)
{
if (null != _interceptPoint && null != _interceptPoint.Target && _interceptPoint.Target is IDisposable)
{
((IDisposable)_interceptPoint.Target).Dispose();
}
}
}
}
================================================
FILE: src/ServiceWire/Aspects/InterceptPoint.cs
================================================
namespace ServiceWire.Aspects
{
public class InterceptPoint
{
public int Id { get; set; }
public object Target { get; set; }
public CrossCuttingConcerns Cut { get; set; }
}
}
================================================
FILE: src/ServiceWire/Aspects/Interceptor.cs
================================================
using System;
namespace ServiceWire.Aspects
{
public static class Interceptor
{
public static TTarget Intercept<TTarget>(TTarget target, CrossCuttingConcerns crossCuttingConcerns, ISerializer serializer = null, ICompressor compressor = null, ILog logger = null, IStats stats = null) where TTarget : class
{
return Intercept<TTarget>(0, target, crossCuttingConcerns, serializer, compressor, logger, stats);
}
public static TTarget Intercept<TTarget>(int id, TTarget target, CrossCuttingConcerns crossCuttingConcerns, ISerializer serializer = null, ICompressor compressor = null, ILog logger = null, IStats stats = null) where TTarget : class
{
if (!typeof(TTarget).IsInterface) throw new ArgumentException("TTarget not an interface");
if (null == target) throw new ArgumentNullException("target");
if (null == serializer) serializer = new DefaultSerializer();
if (null == compressor) compressor = new DefaultCompressor();
TTarget interceptedTarget = ProxyFactory.CreateProxy<TTarget>(typeof(InterceptChannel),
typeof(InterceptPoint),
new InterceptPoint
{
Id = id,
Target = target,
Cut = crossCuttingConcerns
},
serializer,
compressor,
logger,
stats);
return interceptedTarget;
}
}
}
================================================
FILE: src/ServiceWire/Channel.cs
================================================
using System;
namespace ServiceWire
{
public abstract class Channel : IDisposable
{
protected Type _serviceType;
protected ILog _logger;
protected IStats _stats;
internal readonly ISerializer _serializer;
internal readonly ICompressor _compressor;
public Channel(ISerializer serializer, ICompressor compressor, ILog logger = null, IStats stats = null)
{
_serializer = serializer ?? new DefaultSerializer();
_compressor = compressor ?? new DefaultCompressor();
_logger = logger ?? new NullLogger();
_stats = stats ?? new NullStats();
}
[Obsolete]
public void InjectLoggerStats(ILog logger, IStats stats)
{
_logger = logger;
_stats = stats;
}
/// <summary>
/// Invokes the method with the specified parameters.
/// </summary>
/// <param name="parameters">Parameters for the method call</param>
/// <returns>An array of objects containing the return value (index 0) and the parameters used to call
/// the method, including any marked as "ref" or "out"</returns>
protected abstract object[] InvokeMethod(string metaData, params object[] parameters);
/// <summary>
/// Channel must implement an interface synchronization method.
/// This method asks the server for a list of identifiers paired with method
/// names and -parameter types. This is used when invoking methods server side.
/// When username and password supplied, zero knowledge encryption is used.
/// </summary>
protected abstract void SyncInterface(Type serviceType,
string username = null, string password = null);
#region IDisposable Members
protected bool _disposed = false;
public void Dispose()
{
//MS recommended dispose pattern - prevents GC from disposing again
Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract void Dispose(bool disposing);
#endregion
}
}
================================================
FILE: src/ServiceWire/DefaultCompressor.cs
================================================
using System.IO;
using System.IO.Compression;
namespace ServiceWire
{
public class DefaultCompressor : ICompressor
{
public byte[] Compress(byte[] data)
{
using (var msCompressed = new MemoryStream())
{
using (var msObj = new MemoryStream(data))
{
using (GZipStream gzs = new GZipStream(msCompressed, CompressionMode.Compress))
{
msObj.CopyTo(gzs);
}
}
return msCompressed.ToArray();
}
}
public byte[] DeCompress(byte[] compressedBytes)
{
using (var msObj = new MemoryStream())
{
using (var msCompressed = new MemoryStream(compressedBytes))
using (var gzs = new GZipStream(msCompressed, CompressionMode.Decompress))
{
gzs.CopyTo(msObj);
}
msObj.Seek(0, SeekOrigin.Begin);
return msObj.ToArray();
}
}
}
}
================================================
FILE: src/ServiceWire/DefaultSerializer.cs
================================================
using System;
using System.IO;
using System.Text.Json;
namespace ServiceWire
{
public class DefaultSerializer : ISerializer
{
public byte[] Serialize<T>(T obj)
{
if (null == obj) return null;
return JsonSerializer.SerializeToUtf8Bytes<T>(obj);
}
public byte[] Serialize(object obj, string typeConfigName)
{
if (null == obj) return null;
return JsonSerializer.SerializeToUtf8Bytes(obj, typeConfigName.ToType());
}
public T Deserialize<T>(byte[] bytes)
{
if (null == bytes || bytes.Length == 0) return default(T);
return JsonSerializer.Deserialize<T>(bytes);
}
public object Deserialize(byte[] bytes, string typeConfigName)
{
if (null == typeConfigName) throw new ArgumentNullException(nameof(typeConfigName));
var type = typeConfigName.ToType();
if (null == typeConfigName || null == bytes || bytes.Length == 0) return type.GetDefault();
return JsonSerializer.Deserialize(bytes, typeConfigName.ToType());
}
}
}
================================================
FILE: src/ServiceWire/DefaultTypeMaker.cs
================================================
using System;
namespace ServiceWire
{
internal class DefaultTypeMaker
{
public object GetDefault(Type t)
{
return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null);
}
public T GetDefaultGeneric<T>()
{
return default(T);
}
}
}
================================================
FILE: src/ServiceWire/Host.cs
================================================
using ServiceWire.ZeroKnowledge;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
namespace ServiceWire
{
public abstract class Host : IDisposable
{
protected volatile bool _isOpen;
protected volatile bool _continueListening = true;
protected bool _useCompression = false; //default is false
protected int _compressionThreshold = 131072; //128KB
protected ILog _log = new NullLogger();
protected IStats _stats = new NullStats();
protected readonly ISerializer _serializer;
protected readonly ICompressor _compressor;
protected IZkRepository _zkRepository = new ZkNullRepository();
private volatile bool _requireZk = false;
protected ConcurrentDictionary<string, int> _serviceKeys = new ConcurrentDictionary<string, int>();
protected ConcurrentDictionary<int, ServiceInstance> _services = new ConcurrentDictionary<int, ServiceInstance>();
protected readonly ParameterTransferHelper _parameterTransferHelper;
public Host(ISerializer serializer, ICompressor compressor)
{
_serializer = serializer ?? new DefaultSerializer();
_compressor = compressor ?? new DefaultCompressor();
_parameterTransferHelper = new ParameterTransferHelper(_serializer, _compressor);
}
public IZkRepository ZkRepository
{
get
{
return _zkRepository;
}
set
{
_zkRepository = value;
if (_zkRepository is ZkNullRepository)
_requireZk = false;
else
_requireZk = true;
}
}
public IStats Stats
{
get
{
return _stats;
}
set
{
_stats = value ?? _stats;
}
}
public ILog Log
{
get
{
return _log;
}
set
{
_log = value ?? _log;
}
}
protected bool Continue
{
get
{
return _continueListening;
}
set
{
_continueListening = value;
}
}
/// <summary>
/// Enable parameter compression. Default is false. There is a performance penalty
/// when using compression that should be weighed against network transmission
/// costs of large data parameters being serialized across the wire.
/// </summary>
public bool UseCompression
{
get
{
return _useCompression;
}
set
{
_useCompression = value;
}
}
/// <summary>
/// Compression, if enabled, occurs once a parameter exceeds this value
/// in the number of bytes. Strings, byte and char arrays, and complex serialized types.
/// The minimum is 1024 bytes. The default is 128KB.
/// </summary>
public int CompressionThreshold
{
get
{
return _compressionThreshold;
}
set
{
_compressionThreshold = value;
if (_compressionThreshold < 1024) _compressionThreshold = 1024;
}
}
/// <summary>
/// Add this service implementation to the host.
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <param name="service">The singleton implementation.</param>
public void AddService<TService>(TService service) where TService : class
{
try
{
if (_isOpen) throw new Exception("Service cannot be added after the host is opened.");
var serviceType = typeof(TService);
if (!serviceType.IsInterface) throw new ArgumentException("TService must be an interface.", "TService");
//serviceType.ValidateServiceInterface(); //throws if one class in the interface or its members is not serializable
var serviceKey = serviceType.ToConfigName(); // serviceType.AssemblyQualifiedName ?? serviceType.FullName;
if (_serviceKeys.ContainsKey(serviceKey)) throw new Exception("Service already added. Only one instance allowed.");
int keyIndex = _serviceKeys.Count;
_serviceKeys.TryAdd(serviceKey, keyIndex);
var instance = CreateMethodMap(keyIndex, serviceType, service);
_services.TryAdd(keyIndex, instance);
}
catch (Exception e)
{
_log.Fatal("AddServive exception on {0}. Error: {1}", service.GetType(), e.ToString().Flatten());
throw;
}
}
/// <summary>
/// Loads all methods from interfaces and assigns an identifier
/// to each. These are later synchronized with the client.
/// </summary>
private ServiceInstance CreateMethodMap(int keyIndex, Type serviceType, object service)
{
var instance = new ServiceInstance()
{
KeyIndex = keyIndex,
InterfaceType = serviceType,
InterfaceMethods = new ConcurrentDictionary<int, MethodInfo>(),
MethodParametersByRef = new ConcurrentDictionary<int, bool[]>(),
SingletonInstance = service
};
var currentMethodIdent = 0;
if (serviceType.IsInterface)
{
var methodInfos = serviceType.GetMethods();
foreach (var mi in methodInfos)
{
instance.InterfaceMethods.TryAdd(currentMethodIdent, mi);
var parameterInfos = mi.GetParameters();
var isByRef = new bool[parameterInfos.Length];
for (int i = 0; i < isByRef.Length; i++)
isByRef[i] = parameterInfos[i].ParameterType.IsByRef;
instance.MethodParametersByRef.TryAdd(currentMethodIdent, isByRef);
currentMethodIdent++;
}
}
var interfaces = serviceType.GetInterfaces();
foreach (var interfaceType in interfaces)
{
var methodInfos = interfaceType.GetMethods();
foreach (var mi in methodInfos)
{
instance.InterfaceMethods.TryAdd(currentMethodIdent, mi);
var parameterInfos = mi.GetParameters();
var isByRef = new bool[parameterInfos.Length];
for (int i = 0; i < isByRef.Length; i++)
isByRef[i] = parameterInfos[i].ParameterType.IsByRef;
instance.MethodParametersByRef.TryAdd(currentMethodIdent, isByRef);
currentMethodIdent++;
}
}
//Create a list of sync infos from the dictionary
var syncSyncInfos = new List<MethodSyncInfo>();
foreach (var kvp in instance.InterfaceMethods)
{
var parameters = kvp.Value.GetParameters();
var parameterTypes = new string[parameters.Length];
for (var i = 0; i < parameters.Length; i++)
parameterTypes[i] = parameters[i].ParameterType.ToConfigName();
syncSyncInfos.Add(new MethodSyncInfo
{
MethodIdent = kvp.Key,
MethodName = kvp.Value.Name,
MethodReturnType = kvp.Value.ReturnType.ToConfigName(),
ParameterTypes = parameterTypes
});
}
var serviceSyncInfo = new ServiceSyncInfo
{
ServiceKeyIndex = keyIndex,
CompressionThreshold = _compressionThreshold,
UseCompression = _useCompression,
MethodInfos = syncSyncInfos.ToArray()
};
instance.ServiceSyncInfo = serviceSyncInfo;
return instance;
}
/// <summary>
/// Opens the host and starts a listener. This listener spawns a new thread (or uses a
/// thread pool thread) for each incoming connection.
/// </summary>
public void Open()
{
_isOpen = true;
StartListener();
}
protected abstract void StartListener();
/// <summary>
/// Closes the host and calls Dispose().
/// </summary>
public void Close()
{
Dispose();
}
protected void ProcessRequest(Stream stream)
{
if (null == stream || (!stream.CanWrite && !stream.CanRead))
{
_log.Error("Cannot process a request on a stream that is not read/write.");
return;
}
ProcessRequest(stream, stream);
}
/// <summary>
/// This method handles all requests from a single client.
/// There is one thread running this method for each connected client.
/// </summary>
/// <param name="readStream">The read/write stream.</param>
/// <param name="writeStream">The read/write stream.</param>
protected virtual void ProcessRequest(Stream readStream, Stream writeStream)
{
if (null == readStream || null == writeStream) return;
var binReader = new BinaryReader(readStream);
var binWriter = new BinaryWriter(writeStream);
bool doContinue = true;
try
{
ZkSession zkSession = null;
do
{
var sw = Stopwatch.StartNew();
try
{
//read message type
var messageType = (MessageType)binReader.ReadInt32();
switch (messageType)
{
case MessageType.ZkInitiate:
zkSession = new ZkSession(_zkRepository, _log, _stats);
doContinue = zkSession.ProcessZkInitiation(binReader, binWriter, sw);
break;
case MessageType.ZkProof:
if (null == zkSession) throw new NullReferenceException("session null");
doContinue = zkSession.ProcessZkProof(binReader, binWriter, sw);
break;
case MessageType.SyncInterface:
ProcessSync(zkSession, binReader, binWriter, sw);
break;
case MessageType.MethodInvocation:
ProcessInvocation(zkSession, binReader, binWriter, sw);
break;
case MessageType.TerminateConnection:
doContinue = false;
break;
default:
doContinue = false;
break;
}
}
catch (Exception e) //do not resume operation on this thread if any errors are unhandled.
{
_log.Error("Error in ProcessRequest: {0}", e.ToString().Flatten());
doContinue = false;
}
sw.Stop();
}
while (doContinue);
}
catch (Exception fatalException)
{
_log.Fatal("Fatal error in ProcessRequest: {0}", fatalException.ToString().Flatten());
}
finally
{
binReader.Close();
binWriter.Close();
}
}
private void ProcessSync(ZkSession session, BinaryReader binReader, BinaryWriter binWriter, Stopwatch sw)
{
var syncCat = "Sync";
string serviceTypeName;
if (_requireZk)
{
//use session and encryption - if throws should not have gotten this far
var len = binReader.ReadInt32();
var bytes = binReader.ReadBytes(len);
var data = session.Crypto.Decrypt(bytes);
serviceTypeName = data.ConverToString();
} else
{
serviceTypeName = binReader.ReadString();
}
int serviceKey;
if (_serviceKeys.TryGetValue(serviceTypeName, out serviceKey))
{
ServiceInstance instance;
if (_services.TryGetValue(serviceKey, out instance))
{
syncCat = instance.InterfaceType.Name;
//Create a list of sync infos from the dictionary
byte[] syncBytes = null;
try
{
//if the serializer fails, we need to send 0 to client to indicate sync error
syncBytes = _serializer.Serialize(instance.ServiceSyncInfo);
}
catch (Exception e)
{
//return zero to indicate failure to client to avoid EOS error on client
binWriter.Write(0);
_log.Debug("SyncInterface error {0}.", e);
}
if (null != syncBytes)
{
if (_requireZk)
{
_log.Debug("Unencrypted data sent to server: {0}", Convert.ToBase64String(syncBytes));
var encData = session.Crypto.Encrypt(syncBytes);
binWriter.Write(encData.Length);
binWriter.Write(encData);
_log.Debug("Encrypted data sent server: {0}", Convert.ToBase64String(encData));
}
else
{
binWriter.Write(syncBytes.Length);
binWriter.Write(syncBytes);
}
}
}
} else
{
//return zero to indicate type or version of type not found
binWriter.Write(0);
}
binWriter.Flush();
_log.Debug("SyncInterface for {0} in {1}ms.", syncCat, sw.ElapsedMilliseconds);
}
private void ProcessInvocation(ZkSession session, BinaryReader binReader, BinaryWriter binWriter, Stopwatch sw)
{
//read service instance key
var cat = "unknown";
var stat = "MethodInvocation";
int invokedServiceKey = binReader.ReadInt32();
ServiceInstance invokedInstance;
if (_services.TryGetValue(invokedServiceKey, out invokedInstance))
{
cat = invokedInstance.InterfaceType.Name;
//read the method identifier
int methodHashCode = binReader.ReadInt32();
if (invokedInstance.InterfaceMethods.ContainsKey(methodHashCode))
{
MethodInfo method;
invokedInstance.InterfaceMethods.TryGetValue(methodHashCode, out method);
stat = method.Name;
bool[] isByRef;
invokedInstance.MethodParametersByRef.TryGetValue(methodHashCode, out isByRef);
//read parameter data
object[] parameters;
if (_requireZk)
{
var len = binReader.ReadInt32();
var encData = binReader.ReadBytes(len);
_log.Debug("Encrypted data received from server: {0}", Convert.ToBase64String(encData));
var data = session.Crypto.Decrypt(encData);
_log.Debug("Decrypted data received from server: {0}", Convert.ToBase64String(data));
using (var ms = new MemoryStream(data))
using (var br = new BinaryReader(ms))
{
parameters = _parameterTransferHelper.ReceiveParameters(br);
}
} else
{
parameters = _parameterTransferHelper.ReceiveParameters(binReader);
}
//invoke the method
object[] returnParameters;
var returnMessageType = MessageType.ReturnValues;
try
{
object returnValue = method.Invoke(invokedInstance.SingletonInstance, parameters);
if (returnValue is Task task)
{
task.GetAwaiter().GetResult();
var prop = task.GetType().GetProperty("Result");
returnValue = prop?.GetValue(task);
}
//the result to the client is the return value (null if void) and the input parameters
returnParameters = new object[1 + parameters.Length];
returnParameters[0] = returnValue;
for (int i = 0; i < parameters.Length; i++)
returnParameters[i + 1] = isByRef[i] ? parameters[i] : null;
}
catch (Exception ex)
{
//an exception was caught. Rethrow it client side
returnParameters = new object[] { (ex is TargetInvocationException && ex.InnerException != null) ? ex.InnerException : ex };
returnMessageType = MessageType.ThrowException;
}
//send the result back to the client
// (1) write the message type
binWriter.Write((int)returnMessageType);
// (2) write the return parameters
if (_requireZk)
{
byte[] data;
using (var ms = new MemoryStream())
using (var bw = new BinaryWriter(ms))
{
_parameterTransferHelper.SendParameters(
invokedInstance.ServiceSyncInfo.UseCompression,
invokedInstance.ServiceSyncInfo.CompressionThreshold,
bw,
returnParameters);
data = ms.ToArray();
}
_log.Debug("Unencrypted data sent server: {0}", Convert.ToBase64String(data));
var encData = session.Crypto.Encrypt(data);
_log.Debug("Encrypted data sent server: {0}", Convert.ToBase64String(encData));
binWriter.Write(encData.Length);
binWriter.Write(encData);
} else
{
_parameterTransferHelper.SendParameters(
invokedInstance.ServiceSyncInfo.UseCompression,
invokedInstance.ServiceSyncInfo.CompressionThreshold,
binWriter,
returnParameters);
}
} else
{
binWriter.Write((int)MessageType.UnknownMethod);
}
} else
{
binWriter.Write((int)MessageType.UnknownMethod);
}
//flush
binWriter.Flush();
_stats.Log(cat, stat, sw.ElapsedMilliseconds);
}
#region IDisposable Members
private bool _disposed = false;
public void Dispose()
{
//MS recommended dispose pattern - prevents GC from disposing again
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
_disposed = true; //prevent second call to Dispose
if (disposing)
{
if (_log is Logger log) log.FlushLog();
if (_stats is Stats stat) stat.FlushLog();
_isOpen = false;
Continue = false;
foreach (var instance in _services)
{
if (instance.Value.SingletonInstance is IDisposable disposable) disposable.Dispose();
}
}
}
#endregion
}
}
================================================
FILE: src/ServiceWire/IChannelIdentifier.cs
================================================
namespace ServiceWire
{
public interface IChannelIdentifier
{
}
}
================================================
FILE: src/ServiceWire/ICompressor.cs
================================================
namespace ServiceWire
{
public interface ICompressor
{
byte[] Compress(byte[] data);
byte[] DeCompress(byte[] compressedBytes);
}
}
================================================
FILE: src/ServiceWire/IDvChannel.cs
================================================
namespace ServiceWire
{
/// <summary>
/// The channel behavior exposed on the client level.
/// </summary>
public interface IDvChannel
{
/// <summary>
/// Returns true if client is connected to the server.
/// </summary>
bool IsConnected { get; }
}
}
================================================
FILE: src/ServiceWire/ILog.cs
================================================
namespace ServiceWire
{
public interface ILog
{
void Debug(string formattedMessage, params object[] args);
void Info(string formattedMessage, params object[] args);
void Warn(string formattedMessage, params object[] args);
void Error(string formattedMessage, params object[] args);
void Fatal(string formattedMessage, params object[] args);
}
}
================================================
FILE: src/ServiceWire/ISerializer.cs
================================================
namespace ServiceWire
{
public interface ISerializer
{
byte[] Serialize<T>(T obj);
byte[] Serialize(object obj, string typeConfigName);
T Deserialize<T>(byte[] bytes);
object Deserialize(byte[] bytes, string typeConfigName);
}
}
================================================
FILE: src/ServiceWire/IStats.cs
================================================
namespace ServiceWire
{
public interface IStats
{
void Log(string name, float value);
void Log(string category, string name, float value);
}
}
================================================
FILE: src/ServiceWire/LogLevel.cs
================================================
namespace ServiceWire
{
public enum LogLevel
{
None = 0,
Fatal = 1,
Error = 2,
Warn = 3,
Info = 4,
Debug = 5
}
}
================================================
FILE: src/ServiceWire/LogOptions.cs
================================================
namespace ServiceWire
{
public enum LogOptions
{
LogOnlyToFile,
LogOnlyToConsole,
LogToBoth
}
}
================================================
FILE: src/ServiceWire/LogRollOptions.cs
================================================
namespace ServiceWire
{
public enum LogRollOptions
{
Daily,
Hourly,
Size
}
}
================================================
FILE: src/ServiceWire/Logger.cs
================================================
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
namespace ServiceWire
{
public class Logger : LoggerBase, ILog
{
private LogLevel _logLevel = LogLevel.Error;
/// <summary>
/// Set to Debug for all logging on. To None for no logging.
/// Order is: None, Fatal, Error, Warn, Info, Debug
/// </summary>
public LogLevel LogLevel
{
get { return _logLevel; }
set { _logLevel = value; }
}
private const string LogFilePrefixDefault = "log-";
private const string LogFileExtensionDefault = ".txt";
public Logger(string logDirectory = null,
string logFilePrefix = null,
string logFileExtension = null,
LogLevel logLevel = LogLevel.Error,
int messageBufferSize = 32,
LogOptions options = LogOptions.LogOnlyToFile,
LogRollOptions rollOptions = LogRollOptions.Daily,
int rollMaxMegaBytes = 1024,
bool useUtcTimeStamp = false)
{
_logDirectory = logDirectory ?? Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "logs");
Directory.CreateDirectory(_logDirectory); //will throw if unable - does not throw if already exists
_logFilePrefix = logFilePrefix ?? LogFilePrefixDefault;
_logFileExtension = logFileExtension ?? LogFileExtensionDefault;
_logLevel = logLevel;
_messageBufferSize = messageBufferSize;
_rollOptions = rollOptions;
_rollMaxMegaBytes = rollMaxMegaBytes;
_useUtcTimeStamp = useUtcTimeStamp;
LogOptions = options; //setter validates
if (_messageBufferSize < 1) _messageBufferSize = 1;
if (_messageBufferSize > 4096) _messageBufferSize = 4096;
if (_rollOptions == LogRollOptions.Size)
{
if (_rollMaxMegaBytes < 1) _rollMaxMegaBytes = 1;
if (_rollMaxMegaBytes < 4096) _rollMaxMegaBytes = 4096;
}
}
private void WriteMessage(LogLevel logLevel, string formattedMessage, params object[] args)
{
if (null == formattedMessage) return; //do nothing
if ((int) logLevel <= (int) _logLevel)
{
string msg = (null != args && args.Length > 0)
? string.Format(formattedMessage, args)
: formattedMessage;
_logQueue.Enqueue(new string[] { string.Format("{0}\t{1}\t{2}", GetTimeStamp(), logLevel, msg) });
if (_logQueue.Count >= _messageBufferSize)
Task.Factory.StartNew(() => WriteBuffer(_messageBufferSize));
}
}
public void Debug(string formattedMessage, params object[] args)
{
WriteMessage(LogLevel.Debug, formattedMessage, args);
}
public void Info(string formattedMessage, params object[] args)
{
WriteMessage(LogLevel.Info, formattedMessage, args);
}
public void Warn(string formattedMessage, params object[] args)
{
WriteMessage(LogLevel.Warn, formattedMessage, args);
}
public void Error(string formattedMessage, params object[] args)
{
WriteMessage(LogLevel.Error, formattedMessage, args);
}
public void Fatal(string formattedMessage, params object[] args)
{
WriteMessage(LogLevel.Fatal, formattedMessage, args);
}
}
}
================================================
FILE: src/ServiceWire/LoggerBase.cs
================================================
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
namespace ServiceWire
{
public abstract class LoggerBase
{
protected object _syncRoot = new object();
protected string _logDirectory = null;
protected string _logFilePrefix = null;
protected string _logFileExtension = null;
protected bool _useUtcTimeStamp = false;
protected ConcurrentQueue<string[]> _logQueue = new ConcurrentQueue<string[]>();
protected LogOptions _options = LogOptions.LogOnlyToFile;
protected LogRollOptions _rollOptions = LogRollOptions.Daily;
protected string _logFileNameFormat = null;
protected int _messageBufferSize = 32;
protected int _rollMaxMegaBytes = 1024;
public LogOptions LogOptions
{
get { return _options; }
set
{
_options = value;
if (_options != LogOptions.LogOnlyToConsole)
{
if (!_logFileExtension.StartsWith(".")) _logFileExtension = "." + _logFileExtension;
_logFileNameFormat = Path.Combine(_logDirectory, _logFilePrefix + "{0}" + _logFileExtension);
}
}
}
public virtual void FlushLog()
{
WriteBuffer(int.MaxValue);
}
protected const string TimeStampPattern = "yyyy-MM-ddTHH:mm:ss.fff";
protected string GetTimeStamp()
{
return _useUtcTimeStamp
? DateTime.UtcNow.ToString(TimeStampPattern)
: DateTime.Now.ToString(TimeStampPattern);
}
protected string GetTimeStamp(DateTime dt)
{
return _useUtcTimeStamp
? dt.ToUniversalTime().ToString(TimeStampPattern)
: dt.ToString(TimeStampPattern);
}
protected void WriteBuffer(int count)
{
var list = new List<string>();
for (int i = 0; i < count; i++)
{
string[] msg;
_logQueue.TryDequeue(out msg);
if (null == msg) break;
list.AddRange(msg);
}
if (list.Count == 0) return; //nothing to log
var lines = list.ToArray();
if (_options == LogOptions.LogOnlyToConsole || _options == LogOptions.LogToBoth)
{
Console.Write(lines);
}
if (_options == LogOptions.LogOnlyToFile || _options == LogOptions.LogToBoth)
{
WriteToFile(lines);
}
}
private void WriteToFile(string[] lines)
{
lock (_syncRoot)
{
try
{
var fileName = GetFileName();
File.AppendAllLines(fileName, lines);
}
catch
{
//todo ?
}
}
}
private string _currentFileName = null;
private int _currentFileOffset = -1;
private int _currentWritesCount = 0;
private string GetFileName()
{
//by size
if (_rollOptions == LogRollOptions.Size)
{
if (_currentFileOffset < 0) _currentFileOffset = GetCurrentFileOffset();
if (null == _currentFileName)
{
_currentFileName = GetSizeFileName(_currentFileOffset);
return _currentFileName;
}
//should we check size?
if (_currentWritesCount * _messageBufferSize >= 3200) //100 writes at 32 per
{
_currentWritesCount = 0; //reset
var fi = new FileInfo(_currentFileName);
if (fi.Length > _rollMaxMegaBytes * 1024 * 1024)
{
_currentFileOffset++;
_currentFileName = GetSizeFileName(_currentFileOffset);
}
}
return _currentFileName;
}
//based on roll options
if (_rollOptions == LogRollOptions.Hourly)
{
if (_useUtcTimeStamp) return string.Format(_logFileNameFormat, DateTime.UtcNow.ToString(ToDateHourPattern));
return string.Format(_logFileNameFormat, DateTime.Now.ToString(ToDateHourPattern));
}
if (_useUtcTimeStamp) return string.Format(_logFileNameFormat, DateTime.UtcNow.ToString(ToDateOnlyPattern));
return string.Format(_logFileNameFormat, DateTime.Now.ToString(ToDateOnlyPattern));
}
private const string ToDateOnlyPattern = "yyyyMMdd";
private const string ToDateHourPattern = "yyyyMMdd-HH";
private int GetCurrentFileOffset()
{
return Directory.GetFiles(_logDirectory, _logFilePrefix + "*").Length;
}
private const string FileNameFormatSizePattern = "00000000";
private string GetSizeFileName(int offset)
{
return string.Format(_logFileNameFormat, offset.ToString(FileNameFormatSizePattern));
}
}
}
================================================
FILE: src/ServiceWire/MemoryDetail.cs
================================================
using System;
namespace ServiceWire
{
public class MemoryDetail
{
public ulong TotalVisibleMemorySize { get; set; }
public ulong TotalVirtualMemorySize { get; set; }
public ulong FreePhysicalMemory { get; set; }
public ulong FreeVirtualMemory { get; set; }
}
}
================================================
FILE: src/ServiceWire/MessageType.cs
================================================
namespace ServiceWire
{
public enum MessageType
{
TerminateConnection = 0,
MethodInvocation = 1,
ReturnValues = 2,
UnknownMethod = 3,
ThrowException = 4,
SyncInterface = 5,
ZkInitiate = 20,
ZkProof = 21
};
}
================================================
FILE: src/ServiceWire/MethodSyncInfo.cs
================================================
using System;
using System.Runtime.Serialization;
namespace ServiceWire
{
[Serializable, DataContract]
public class MethodSyncInfo
{
[DataMember(Order = 1)]
public int MethodIdent { get; set; }
[DataMember(Order = 2)]
public string MethodName { get; set; }
[DataMember(Order = 3)]
public string MethodReturnType { get; set; }
[DataMember(Order = 4)]
public string[] ParameterTypes { get; set; }
}
}
================================================
FILE: src/ServiceWire/NamedPipes/DefaultNamedPipeServerStreamFactory.cs
================================================
using System.IO.Pipes;
namespace ServiceWire.NamedPipes
{
public class DefaultNamedPipeServerStreamFactory : INamedPipeServerStreamFactory
{
public NamedPipeServerStream Create(string pipeName, PipeDirection direction, int maxNumberOfServerInstances,
PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize)
{
return new NamedPipeServerStream(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize);
}
}
}
================================================
FILE: src/ServiceWire/NamedPipes/INamedPipeServerStreamFactory.cs
================================================
using System.IO.Pipes;
namespace ServiceWire.NamedPipes
{
public interface INamedPipeServerStreamFactory
{
NamedPipeServerStream Create(string pipeName, PipeDirection direction, int maxNumberOfServerInstances,
PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize);
}
}
================================================
FILE: src/ServiceWire/NamedPipes/NpChannel.cs
================================================
using System;
using System.IO;
using System.IO.Pipes;
namespace ServiceWire.NamedPipes
{
public class NpChannel : StreamingChannel
{
private readonly NamedPipeClientStream _clientStream;
private readonly NpChannelIdentifier _channelIdentifier;
/// <summary>
/// Creates a connection to the concrete object handling method calls on the pipeName server side
/// </summary>
/// <param name="serviceType"></param>
/// <param name="npEndPoint"></param>
/// <param name="serializer">Inject your own serializer for complex objects and avoid using the Newtonsoft JSON DefaultSerializer.</param>
public NpChannel(Type serviceType, NpEndPoint npEndPoint, ISerializer serializer, ICompressor compressor, ILog logger = null, IStats stats = null)
: base(serializer, compressor, logger, stats)
{
_serviceType = serviceType;
_channelIdentifier = new NpChannelIdentifier(npEndPoint);
_clientStream = new NamedPipeClientStream(npEndPoint.ServerName, npEndPoint.PipeName, PipeDirection.InOut);
_clientStream.Connect(npEndPoint.ConnectTimeOutMs);
_stream = new BufferedStream(_clientStream);
_binReader = new BinaryReader(_clientStream);
_binWriter = new BinaryWriter(_clientStream);
try
{
SyncInterface(_serviceType);
}
catch (Exception)
{
this.Dispose(true);
throw;
}
}
protected override IChannelIdentifier ChannelIdentifier => _channelIdentifier;
public override bool IsConnected { get { return (null != _clientStream) && _clientStream.IsConnected; } }
}
}
================================================
FILE: src/ServiceWire/NamedPipes/NpChannelIdentifier.cs
================================================
using System;
namespace ServiceWire.NamedPipes
{
internal class NpChannelIdentifier : IChannelIdentifier, IEquatable<NpChannelIdentifier>
{
public string ServerName { get; private set; }
public string PipeName { get; private set; }
public NpChannelIdentifier(NpEndPoint npEndPoint)
{
ServerName = npEndPoint.ServerName;
PipeName = npEndPoint.PipeName;
}
public bool Equals(NpChannelIdentifier other)
{
return ServerName == other.ServerName
&& PipeName == other.PipeName;
}
public override bool Equals(object obj)
{
if (obj is NpChannelIdentifier other)
{
return Equals(other);
}
return false;
}
public override int GetHashCode()
{
unchecked
{
return ServerName.GetHashCode() + PipeName.GetHashCode();
}
}
}
}
================================================
FILE: src/ServiceWire/NamedPipes/NpClient.cs
================================================
using System;
namespace ServiceWire.NamedPipes
{
public class NpClient<TInterface> : IDisposable where TInterface : class
{
private readonly TInterface _proxy;
public TInterface Proxy { get { return _proxy; } }
public bool IsConnected
{
get
{
return (_proxy != null) && (_proxy as NpChannel).IsConnected;
}
}
/// <summary>
/// Create a named pipes client.
/// </summary>
/// <param name="npAddress"></param>
/// <param name="serializer">Inject your own serializer for complex objects and avoid using the Newtonsoft JSON DefaultSerializer.</param>
/// <param name="compressor">Inject your own compressor and avoid using the standard GZIP DefaultCompressor.</param>
public NpClient(NpEndPoint npAddress, ISerializer serializer = null, ICompressor compressor = null, ILog logger = null, IStats stats = null)
{
if (null == serializer) serializer = new DefaultSerializer();
if (null == compressor) compressor = new DefaultCompressor();
if (null == logger) logger = new NullLogger();
if (null == stats) stats = new NullStats();
_proxy = NpProxy.CreateProxy<TInterface>(npAddress, serializer, compressor, logger, stats);
}
#region IDisposable Members
private bool _disposed = false;
public void Dispose()
{
//MS recommended dispose pattern - prevents GC from disposing again
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
_disposed = true; //prevent second call to Dispose
if (disposing)
{
(_proxy as NpChannel).Dispose();
}
}
}
#endregion
}
}
================================================
FILE: src/ServiceWire/NamedPipes/NpEndPoint.cs
================================================
namespace ServiceWire.NamedPipes
{
public class NpEndPoint
{
public NpEndPoint(string pipeName, int connectTimeOutMs = 2500)
: this(".", pipeName, connectTimeOutMs)
{
}
public NpEndPoint(string serverName, string pipeName, int connectTimeOutMs = 2500)
{
this.ServerName = serverName;
this.PipeName = pipeName;
this.ConnectTimeOutMs = connectTimeOutMs;
}
public string ServerName { get; private set; }
public string PipeName { get; private set; }
public int ConnectTimeOutMs { get; private set; }
}
}
================================================
FILE: src/ServiceWire/NamedPipes/NpHost.cs
================================================
using System;
using System.IO;
namespace ServiceWire.NamedPipes
{
public class NpHost : Host
{
private readonly NpListener _listener;
private readonly string _pipeName;
private bool _useThreadPool = false;
/// <summary>
/// Get or set whether the host should use regular or thread pool threads.
/// </summary>
public bool UseThreadPool
{
get { return _useThreadPool; }
set
{
if (_isOpen)
throw new Exception("The host is already open");
_useThreadPool = value;
}
}
/// <summary>
/// Constructs an instance of the host and starts listening for incoming connections.
/// All listener threads are regular background threads.
///
/// NOTE: the instance is not automatically thread safe!
/// </summary>
/// <param name="pipeName">The pipe name for incoming requests</param>
/// <param name="log"></param>
/// <param name="stats"></param>
/// <param name="serializer">Inject your own serializer for complex objects and avoid using the Newtonsoft JSON DefaultSerializer.</param>
/// <param name="compressor">Inject your own compressor and avoid using the standard GZIP DefaultCompressor.</param>
/// <param name="streamFactory">Inject your own factory for creating the named pipe server. Can be used with NamedPipeServerStreamAcl to set the ACL on Windows platforms.</param>
public NpHost(string pipeName, ILog log = null, IStats stats = null, ISerializer serializer = null, ICompressor compressor = null, INamedPipeServerStreamFactory streamFactory = null)
: base(serializer, compressor)
{
base.Log = log;
base.Stats = stats;
_pipeName = pipeName;
_listener = new NpListener(_pipeName, log: base.Log, stats: base.Stats, streamFactory: streamFactory);
_listener.RequestReieved += ClientConnectionMade;
}
/// <summary>
/// Gets the end point this host is listening on
/// </summary>
public string PipeName
{
get { return _pipeName; }
}
protected override void StartListener()
{
_listener.Start(); //start listening in the background
}
/// <summary>
/// This method handles all requests on separate thread per client connection.
/// There is one thread running this method for each connected client.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void ClientConnectionMade(object sender, PipeClientConnectionEventArgs args)
{
var stream = new BufferedStream(args.PipeStream);
base.ProcessRequest(stream);
}
#region IDisposable Members
private bool _disposed = false;
protected override void Dispose(bool disposing)
{
if (!_disposed)
{
_disposed = true; //prevent second call to Dispose
if (disposing)
{
_listener.Stop();
}
}
}
#endregion
}
}
================================================
FILE: src/ServiceWire/NamedPipes/NpListener.cs
================================================
using System;
using System.IO.Pipes;
using System.Threading;
using System.Threading.Tasks;
namespace ServiceWire.NamedPipes
{
public class NpListener
{
private bool _running;
private readonly EventWaitHandle _terminateHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
private readonly int _maxConnections = 254;
private readonly ILog _log;
private readonly IStats _stats;
private readonly INamedPipeServerStreamFactory _streamFactory;
public string PipeName { get; set; }
public event EventHandler<PipeClientConnectionEventArgs> RequestReieved;
public NpListener(string pipeName, int maxConnections = 254, ILog log = null, IStats stats = null, INamedPipeServerStreamFactory streamFactory = null)
{
_log = log ?? new NullLogger();
_stats = stats ?? new NullStats();
if (maxConnections > 254) maxConnections = 254;
_maxConnections = maxConnections;
this.PipeName = pipeName;
_streamFactory = streamFactory ?? new DefaultNamedPipeServerStreamFactory();
}
public void Start()
{
_running = true;
Task.Factory.StartNew(() => ServerLoop(), TaskCreationOptions.LongRunning);
}
public void Stop()
{
if (_running)
{
_running = false;
//make fake connection to terminate the waiting stream
try
{
using (var client = new NamedPipeClientStream(PipeName))
{
client.Connect(50);
}
}
catch (Exception e)
{
_log.Error("Stop error: {0}", e.ToString().Flatten());
}
_terminateHandle.WaitOne();
}
}
private void ServerLoop()
{
try
{
while (_running)
{
ProcessNextClient();
}
}
catch (Exception e)
{
_log.Fatal("ServerLoop fatal error: {0}", e.ToString().Flatten());
}
finally
{
_terminateHandle.Set();
}
}
private void ProcessClientThread(NamedPipeServerStream pipeStream)
{
try
{
if (this.RequestReieved != null) //has event subscribers
{
var args = new PipeClientConnectionEventArgs(pipeStream);
RequestReieved(this, args);
}
}
catch (Exception e)
{
_log.Error("ProcessClientThread error: {0}", e.ToString().Flatten());
}
finally
{
if (pipeStream.IsConnected) pipeStream.Close();
pipeStream.Dispose();
}
}
public void ProcessNextClient()
{
try
{
var pipeStream = _streamFactory.Create(PipeName, PipeDirection.InOut, _maxConnections, PipeTransmissionMode.Byte, PipeOptions.None, 512, 512);
pipeStream.WaitForConnection();
//Task.Factory.StartNew(() => ProcessClientThread(pipeStream), TaskCreationOptions.LongRunning);
Task.Factory.StartNew(() => ProcessClientThread(pipeStream));
}
catch (Exception e)
{
//If there are no more avail connections (254 is in use already) then just keep looping until one is avail
_log.Error("ProcessNextClient error: {0}", e.ToString().Flatten());
}
}
}
// Defines the data protocol for reading and writing strings on our stream
// Contains the method executed in the context of the impersonated user
}
================================================
FILE: src/ServiceWire/NamedPipes/NpProxy.cs
================================================
namespace ServiceWire.NamedPipes
{
public class NpProxy
{
public static TInterface CreateProxy<TInterface>(NpEndPoint npAddress, ISerializer serializer, ICompressor compressor, ILog logger, IStats stats) where TInterface : class
{
return ProxyFactory.CreateProxy<TInterface>(typeof(NpChannel), typeof(NpEndPoint), npAddress, serializer, compressor, logger, stats);
}
}
}
================================================
FILE: src/ServiceWire/NamedPipes/PipeClientConnectionEventArgs.cs
================================================
using System;
using System.IO.Pipes;
namespace ServiceWire.NamedPipes
{
public class PipeClientConnectionEventArgs : EventArgs
{
public PipeClientConnectionEventArgs(NamedPipeServerStream pipeStream)
{
this.PipeStream = pipeStream;
}
public NamedPipeServerStream PipeStream { get; private set; }
}
}
================================================
FILE: src/ServiceWire/NamedPipes/ReadFileToStream.cs
================================================
using System.IO;
namespace ServiceWire.NamedPipes
{
public class ReadFileToStream
{
private readonly string _fileName;
private readonly StreamString _streamString;
public ReadFileToStream(StreamString str, string filename)
{
_fileName = filename;
_streamString = str;
}
public void Start()
{
_streamString.WriteString(File.ReadAllText(_fileName));
}
}
}
================================================
FILE: src/ServiceWire/NamedPipes/StreamString.cs
================================================
using System;
using System.IO;
using System.Text;
namespace ServiceWire.NamedPipes
{
public class StreamString
{
private readonly Stream _ioStream;
private readonly UnicodeEncoding _streamEncoding;
public StreamString(Stream ioStream)
{
this._ioStream = ioStream;
_streamEncoding = new UnicodeEncoding();
}
public string ReadString()
{
int len = 0;
len = _ioStream.ReadByte() * 256;
len += _ioStream.ReadByte();
byte[] inBuffer = new byte[len];
_ioStream.Read(inBuffer, 0, len);
return _streamEncoding.GetString(inBuffer);
}
public int WriteString(string outString)
{
byte[] outBuffer = _streamEncoding.GetBytes(outString);
int len = outBuffer.Length;
if (len > UInt16.MaxValue)
{
len = (int)UInt16.MaxValue;
}
_ioStream.WriteByte((byte)(len / 256));
_ioStream.WriteByte((byte)(len & 255));
_ioStream.Write(outBuffer, 0, len);
_ioStream.Flush();
return outBuffer.Length + 2;
}
}
}
================================================
FILE: src/ServiceWire/NetExtensions.cs
================================================
using System;
using System.Text.RegularExpressions;
namespace ServiceWire
{
public static class NetExtensions
{
private const string _netFwCoreLib = "mscorlib";
private const string _netCoreCoreLib = "System.Private.CoreLib";
public static string ToConfigName(this Type t)
{
// Do not qualify types from mscorlib/System.Private.CoreLib otherwise calling between process running with different frameworks won't work
// i.e. "System.String, mscorlib" (.NET FW) != "System.String, System.Private.CoreLib" (.NET CORE)
var name = t.Assembly.GetName().Name == _netFwCoreLib || t.Assembly.GetName().Name == _netCoreCoreLib
? t.FullName
: t.AssemblyQualifiedName;
// But since an mscorlib generic container can contain fully qualified types we always need to clean up the name
name = Regex.Replace(name, @", Version=\d+.\d+.\d+.\d+", string.Empty);
name = Regex.Replace(name, @", Culture=\w+", string.Empty);
name = Regex.Replace(name, @", PublicKeyToken=\w+", string.Empty);
name = name.Replace(", " + _netFwCoreLib, string.Empty);
name = name.Replace(", " + _netCoreCoreLib, string.Empty);
return name;
}
public static Type ToType(this string configName)
{
try
{
var result = Type.GetType(configName);
return result;
}
catch (Exception e)
{
Console.WriteLine(e);
}
return null;
}
/// <summary>
/// Returns true if Type inherits from baseType.
/// </summary>
/// <param name="t">The Type extended by this method.</param>
/// <param name="baseType">The base type to find in the inheritance hierarchy.</param>
/// <returns>True if baseType is found. False if not.</returns>
public static bool InheritsFrom(this Type t, Type baseType)
{
Type cur = t.BaseType;
while (cur != null)
{
if (cur.Equals(baseType)) return true;
cur = cur.BaseType;
}
return false;
}
public static object GetDefault(this Type t)
{
var tm = new DefaultTypeMaker();
return tm.GetDefault(t);
}
public static string Flatten(this string src)
{
return src.Replace("\r", ":").Replace("\n", ":");
}
}
}
================================================
FILE: src/ServiceWire/NullLogger.cs
================================================
namespace ServiceWire
{
internal class NullLogger : ILog
{
public void Debug(string formattedMessage, params object[] args)
{
}
public void Info(string formattedMessage, params object[] args)
{
}
public void Warn(string formattedMessage, params object[] args)
{
}
public void Error(string formattedMessage, params object[] args)
{
}
public void Fatal(string formattedMessage, params object[] args)
{
}
}
}
================================================
FILE: src/ServiceWire/NullStats.cs
================================================
namespace ServiceWire
{
internal class NullStats : IStats
{
public void Log(string name, float value)
{
}
public void Log(string category, string name, float value)
{
}
public void LogSys()
{
}
}
}
================================================
FILE: src/ServiceWire/ParameterTransferHelper.cs
================================================
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace ServiceWire
{
public sealed class ParameterTransferHelper
{
[ThreadStatic]
private static Dictionary<Type, byte> _parameterTypes;
private const string NULL_STRING = "\u2811\u16D8\u270C"; //3 chars from 3 different unicode sets
private readonly ISerializer _serializer;
private readonly ICompressor _compressor;
public ParameterTransferHelper(ISerializer serializer, ICompressor compressor)
{
_serializer = serializer ?? new DefaultSerializer();
_compressor = compressor ?? new DefaultCompressor();
}
public void SendParameters(bool useCompression, int compressionThreshold, BinaryWriter writer, params object[] parameters)
{
//write how many parameters are coming
writer.Write(parameters.Length);
//write data for each parameter
foreach (object parameter in parameters)
{
if (parameter == null)
{
writer.Write(ParameterTypes.Null);
} else
{
Type type = parameter.GetType();
byte typeByte = GetParameterType(type);
byte[] dataBytes = null;
switch (typeByte)
{
case ParameterTypes.ByteArray:
dataBytes = (byte[])parameter;
break;
case ParameterTypes.Unknown:
dataBytes = _serializer.Serialize(parameter, type.ToConfigName());
break;
}
if (useCompression)
{
//check for compressable values and compress if required
switch (typeByte)
{
case ParameterTypes.ByteArray:
if (dataBytes.LongLength > compressionThreshold)
{
typeByte = ParameterTypes.CompressedByteArray;
dataBytes = _compressor.Compress(dataBytes);
}
break;
case ParameterTypes.CharArray:
char[] charArray = (char[])parameter;
if (charArray.LongLength > compressionThreshold)
{
typeByte = ParameterTypes.CompressedCharArray;
dataBytes = _compressor.Compress(Encoding.UTF8.GetBytes(charArray));
}
break;
case ParameterTypes.String:
if (((string)parameter).Length > compressionThreshold)
{
typeByte = ParameterTypes.CompressedString;
dataBytes = _compressor.Compress(Encoding.UTF8.GetBytes(((string)parameter)));
}
break;
case ParameterTypes.ArrayString:
var array = (string[])parameter;
var total = (from n in array select n.Length).Sum();
if (total > compressionThreshold)
{
typeByte = ParameterTypes.Unknown;
dataBytes = _compressor.Compress(_serializer.Serialize(array, type.ToConfigName()));
}
break;
case ParameterTypes.Unknown:
if (dataBytes.Length > compressionThreshold)
{
typeByte = ParameterTypes.CompressedUnknown;
dataBytes = _compressor.Compress(dataBytes);
}
break;
}
}
//write the type byte
writer.Write(typeByte);
//write the parameter
switch (typeByte)
{
case ParameterTypes.Bool:
writer.Write((bool)parameter);
break;
case ParameterTypes.Byte:
writer.Write((byte)parameter);
break;
case ParameterTypes.Char:
writer.Write((char)parameter);
break;
case ParameterTypes.CharArray:
char[] charArray = (char[])parameter;
writer.Write(charArray.Length);
writer.Write(charArray);
break;
case ParameterTypes.Decimal:
writer.Write((decimal)parameter);
break;
case ParameterTypes.Double:
writer.Write((double)parameter);
break;
case ParameterTypes.Float:
writer.Write((float)parameter);
break;
case ParameterTypes.Int:
writer.Write((int)parameter);
break;
case ParameterTypes.Long:
writer.Write((long)parameter);
break;
case ParameterTypes.SByte:
writer.Write((sbyte)parameter);
break;
case ParameterTypes.Short:
writer.Write((short)parameter);
break;
case ParameterTypes.String:
writer.Write((string)parameter);
break;
case ParameterTypes.UInt:
writer.Write((uint)parameter);
break;
case ParameterTypes.ULong:
writer.Write((ulong)parameter);
break;
case ParameterTypes.UShort:
writer.Write((ushort)parameter);
break;
case ParameterTypes.Type:
writer.Write(type.ToConfigName());
break;
case ParameterTypes.Guid:
writer.Write(((Guid)parameter).ToByteArray());
break;
case ParameterTypes.DateTime:
writer.Write(((DateTime)parameter).ToString("o"));
break;
case ParameterTypes.ArrayBool:
var bools = (bool[])parameter;
writer.Write(bools.Length);
foreach (var b in bools) writer.Write(b);
break;
case ParameterTypes.ArraySByte:
var sbytes = (sbyte[])parameter;
writer.Write(sbytes.Length);
foreach (var sb in sbytes) writer.Write(sb);
break;
case ParameterTypes.ArrayDecimal:
var decs = (decimal[])parameter;
writer.Write(decs.Length);
foreach (var d in decs) writer.Write(d);
break;
case ParameterTypes.ArrayDouble:
var dbls = (double[])parameter;
writer.Write(dbls.Length);
foreach (var db in dbls) writer.Write(db);
break;
case ParameterTypes.ArrayFloat:
var fls = (float[])parameter;
writer.Write(fls.Length);
foreach (var f in fls) writer.Write(f);
break;
case ParameterTypes.ArrayInt:
var ints = (int[])parameter;
writer.Write(ints.Length);
foreach (var i in ints) writer.Write(i);
break;
case ParameterTypes.ArrayUInt:
var uints = (uint[])parameter;
writer.Write(uints.Length);
foreach (var u in uints) writer.Write(u);
break;
case ParameterTypes.ArrayLong:
var longs = (long[])parameter;
writer.Write(longs.Length);
foreach (var lg in longs) writer.Write(lg);
break;
case ParameterTypes.ArrayULong:
var ulongs = (ulong[])parameter;
writer.Write(ulongs.Length);
foreach (var ul in ulongs) writer.Write(ul);
break;
case ParameterTypes.ArrayShort:
var shorts = (short[])parameter;
writer.Write(shorts.Length);
foreach (var s in shorts) writer.Write(s);
break;
case ParameterTypes.ArrayUShort:
var ushorts = (ushort[])parameter;
writer.Write(ushorts.Length);
foreach (var us in ushorts) writer.Write(us);
break;
case ParameterTypes.ArrayString:
var strings = (string[])parameter;
writer.Write(strings.Length);
foreach (var st in strings) writer.Write(st ?? NULL_STRING);
break;
case ParameterTypes.ArrayType:
var types = (Type[])parameter;
writer.Write(types.Length);
foreach (var t in types)
writer.Write(t.ToConfigName());
break;
case ParameterTypes.ArrayGuid:
var guids = (Guid[])parameter;
writer.Write(guids.Length);
foreach (var g in guids) writer.Write(g.ToByteArray());
break;
case ParameterTypes.ArrayDateTime:
var dts = (DateTime[])parameter;
writer.Write(dts.Length);
foreach (var dt in dts) writer.Write(dt.ToString("o"));
break;
case ParameterTypes.ByteArray:
case ParameterTypes.CompressedByteArray:
case ParameterTypes.CompressedCharArray:
case ParameterTypes.CompressedString:
//write length of data
writer.Write(dataBytes.Length);
//write data
writer.Write(dataBytes);
break;
case ParameterTypes.Unknown:
case ParameterTypes.CompressedUnknown:
//write type name as string
writer.Write(type.ToConfigName());
//write length of data
writer.Write(dataBytes.Length);
//write data
writer.Write(dataBytes);
break;
default:
throw new Exception(string.Format("Unknown type byte '0x{0:X}'", typeByte));
}
}
}
}
public object[] ReceiveParameters(BinaryReader reader)
{
int parameterCount = reader.ReadInt32();
object[] parameters = new object[parameterCount];
for (int i = 0; i < parameterCount; i++)
{
//read type byte
byte typeByte = reader.ReadByte();
if (typeByte == ParameterTypes.Null)
{
parameters[i] = null;
} else
{
switch (typeByte)
{
case ParameterTypes.Bool:
parameters[i] = reader.ReadBoolean();
break;
case ParameterTypes.Byte:
parameters[i] = reader.ReadByte();
break;
case ParameterTypes.ByteArray:
parameters[i] = reader.ReadBytes(reader.ReadInt32());
break;
case ParameterTypes.CompressedByteArray:
parameters[i] = _compressor.DeCompress(reader.ReadBytes(reader.ReadInt32()));
break;
case ParameterTypes.Char:
parameters[i] = reader.ReadChar();
break;
case ParameterTypes.CharArray:
parameters[i] = reader.ReadChars(reader.ReadInt32());
break;
case ParameterTypes.CompressedCharArray:
var ccBytes = _compressor.DeCompress(reader.ReadBytes(reader.ReadInt32()));
parameters[i] = Encoding.UTF8.GetChars(ccBytes);
break;
case ParameterTypes.Decimal:
parameters[i] = reader.ReadDecimal();
break;
case ParameterTypes.Double:
parameters[i] = reader.ReadDouble();
break;
case ParameterTypes.Float:
parameters[i] = reader.ReadSingle();
break;
case ParameterTypes.Int:
parameters[i] = reader.ReadInt32();
break;
case ParameterTypes.Long:
parameters[i] = reader.ReadInt64();
break;
case ParameterTypes.SByte:
parameters[i] = reader.ReadSByte();
break;
case ParameterTypes.Short:
parameters[i] = reader.ReadInt16();
break;
case ParameterTypes.String:
parameters[i] = reader.ReadString();
break;
case ParameterTypes.CompressedString:
var csBytes = _compressor.DeCompress(reader.ReadBytes(reader.ReadInt32()));
parameters[i] = Encoding.UTF8.GetString(csBytes);
break;
case ParameterTypes.UInt:
parameters[i] = reader.ReadUInt32();
break;
case ParameterTypes.ULong:
parameters[i] = reader.ReadUInt64();
break;
case ParameterTypes.UShort:
parameters[i] = reader.ReadUInt16();
break;
case ParameterTypes.Type:
var typeName = reader.ReadString();
parameters[i] = Type.GetType(typeName);
break;
case ParameterTypes.Guid:
parameters[i] = new Guid(reader.ReadBytes(16));
break;
case ParameterTypes.DateTime:
var dtstr = reader.ReadString();
parameters[i] = DateTime.Parse(dtstr, null, DateTimeStyles.RoundtripKind);
break;
case ParameterTypes.ArrayBool:
var blen = reader.ReadInt32();
var bs = new bool[blen];
for (int x = 0; x < blen; x++) bs[x] = reader.ReadBoolean();
parameters[i] = bs;
break;
case ParameterTypes.ArraySByte:
var sblen = reader.ReadInt32();
var sbs = new sbyte[sblen];
for (int x = 0; x < sblen; x++) sbs[x] = reader.ReadSByte();
parameters[i] = sbs;
break;
case ParameterTypes.ArrayDecimal:
var dclen = reader.ReadInt32();
var dcs = new decimal[dclen];
for (int x = 0; x < dclen; x++) dcs[x] = reader.ReadDecimal();
parameters[i] = dcs;
break;
case ParameterTypes.ArrayDouble:
var dblen = reader.ReadInt32();
var dbs = new double[dblen];
for (int x = 0; x < dblen; x++) dbs[x] = reader.ReadDouble();
parameters[i] = dbs;
break;
case ParameterTypes.ArrayFloat:
var flen = reader.ReadInt32();
var fs = new float[flen];
for (int x = 0; x < flen; x++) fs[x] = reader.ReadSingle();
parameters[i] = fs;
break;
case ParameterTypes.ArrayInt:
var ilen = reader.ReadInt32();
var iss = new int[ilen];
for (int x = 0; x < ilen; x++) iss[x] = reader.ReadInt32();
parameters[i] = iss;
break;
case ParameterTypes.ArrayUInt:
var uilen = reader.ReadInt32();
var uis = new uint[uilen];
for (int x = 0; x < uilen; x++) uis[x] = reader.ReadUInt32();
parameters[i] = uis;
break;
case ParameterTypes.ArrayLong:
var llen = reader.ReadInt32();
var ls = new long[llen];
for (int x = 0; x < llen; x++) ls[x] = reader.ReadInt64();
parameters[i] = ls;
break;
case ParameterTypes.ArrayULong:
var ullen = reader.ReadInt32();
var uls = new ulong[ullen];
for (int x = 0; x < ullen; x++) uls[x] = reader.ReadUInt64();
parameters[i] = uls;
break;
case ParameterTypes.ArrayShort:
var sslen = reader.ReadInt32();
var sss = new short[sslen];
for (int x = 0; x < sslen; x++) sss[x] = reader.ReadInt16();
parameters[i] = sss;
break;
case ParameterTypes.ArrayUShort:
var ulen = reader.ReadInt32();
var us = new ushort[ulen];
for (int x = 0; x < ulen; x++) us[x] = reader.ReadUInt16();
parameters[i] = us;
break;
case ParameterTypes.ArrayString:
var slen = reader.ReadInt32();
var ss = new string[slen];
for (int x = 0; x < slen; x++)
{
ss[x] = reader.ReadString();
if (ss[x] == NULL_STRING) ss[x] = null;
}
parameters[i] = ss;
break;
case ParameterTypes.ArrayType:
var tlen = reader.ReadInt32();
var ts = new Type[tlen];
for (int x = 0; x < tlen; x++) ts[x] = Type.GetType(reader.ReadString());
parameters[i] = ts;
break;
case ParameterTypes.ArrayGuid:
var glen = reader.ReadInt32();
var gs = new Guid[glen];
for (int x = 0; x < glen; x++) gs[x] = new Guid(reader.ReadBytes(16));
parameters[i] = gs;
break;
case ParameterTypes.ArrayDateTime:
var dlen = reader.ReadInt32();
var dts = new DateTime[dlen];
for (int x = 0; x < dlen; x++)
{
var adtstr = reader.ReadString();
dts[x] = DateTime.Parse(adtstr, null, DateTimeStyles.RoundtripKind);
}
parameters[i] = dts;
break;
case ParameterTypes.Unknown:
var typeConfigName = reader.ReadString();
var bytes = reader.ReadBytes(reader.ReadInt32());
parameters[i] = _serializer.Deserialize(bytes, typeConfigName);
break;
case ParameterTypes.CompressedUnknown:
var cuTypeConfigName = reader.ReadString();
var cuBytes = _compressor.DeCompress(reader.ReadBytes(reader.ReadInt32()));
parameters[i] = _serializer.Deserialize(cuBytes, cuTypeConfigName);
break;
default:
throw new Exception(string.Format("Unknown type byte '0x{0:X}'", typeByte));
}
}
}
return parameters;
}
private byte GetParameterType(Type type)
{
InitializeParamTypes();
if (_parameterTypes.ContainsKey(type))
return _parameterTypes[type];
return ParameterTypes.Unknown;
}
private void InitializeParamTypes()
{
if (_parameterTypes == null)
{
_parameterTypes = new Dictionary<Type, byte>();
_parameterTypes.Add(typeof(bool), ParameterTypes.Bool);
_parameterTypes.Add(typeof(byte), ParameterTypes.Byte);
_parameterTypes.Add(typeof(sbyte), ParameterTypes.SByte);
_parameterTypes.Add(typeof(char), ParameterTypes.Char);
_parameterTypes.Add(typeof(decimal), ParameterTypes.Decimal);
_parameterTypes.Add(typeof(double), ParameterTypes.Double);
_parameterTypes.Add(typeof(float), ParameterTypes.Float);
_parameterTypes.Add(typeof(int), ParameterTypes.Int);
_parameterTypes.Add(typeof(uint), ParameterTypes.UInt);
_parameterTypes.Add(typeof(long), ParameterTypes.Long);
_parameterTypes.Add(typeof(ulong), ParameterTypes.ULong);
_parameterTypes.Add(typeof(short), ParameterTypes.Short);
_parameterTypes.Add(typeof(ushort), ParameterTypes.UShort);
_parameterTypes.Add(typeof(string), ParameterTypes.String);
_parameterTypes.Add(typeof(byte[]), ParameterTypes.ByteArray);
_parameterTypes.Add(typeof(char[]), ParameterTypes.CharArray);
_parameterTypes.Add(typeof(Type), ParameterTypes.Type);
_parameterTypes.Add(typeof(Guid), ParameterTypes.Guid);
_parameterTypes.Add(typeof(DateTime), ParameterTypes.DateTime);
_parameterTypes.Add(typeof(bool[]), ParameterTypes.ArrayBool);
_parameterTypes.Add(typeof(sbyte[]), ParameterTypes.ArraySByte);
_parameterTypes.Add(typeof(decimal[]), ParameterTypes.ArrayDecimal);
_parameterTypes.Add(typeof(double[]), ParameterTypes.ArrayDouble);
_parameterTypes.Add(typeof(float[]), ParameterTypes.ArrayFloat);
_parameterTypes.Add(typeof(int[]), ParameterTypes.ArrayInt);
_parameterTypes.Add(typeof(uint[]), ParameterTypes.ArrayUInt);
_parameterTypes.Add(typeof(long[]), ParameterTypes.ArrayLong);
_parameterTypes.Add(typeof(ulong[]), ParameterTypes.ArrayULong);
_parameterTypes.Add(typeof(short[]), ParameterTypes.ArrayShort);
_parameterTypes.Add(typeof(ushort[]), ParameterTypes.ArrayUShort);
_parameterTypes.Add(typeof(string[]), ParameterTypes.ArrayString);
_parameterTypes.Add(typeof(Type[]), ParameterTypes.ArrayType);
_parameterTypes.Add(typeof(Guid[]), ParameterTypes.ArrayGuid);
_parameterTypes.Add(typeof(DateTime[]), ParameterTypes.ArrayDateTime);
}
}
}
}
================================================
FILE: src/ServiceWire/ParameterTypes.cs
================================================
namespace ServiceWire
{
internal sealed class ParameterTypes
{
internal const byte Unknown = 0x00;
internal const byte Bool = 0x01;
internal const byte Byte = 0x02;
internal const byte SByte = 0x03;
internal const byte Char = 0x04;
internal const byte Decimal = 0x05;
internal const byte Double = 0x06;
internal const byte Float = 0x07;
internal const byte Int = 0x08;
internal const byte UInt = 0x09;
internal const byte Long = 0x0A;
internal const byte ULong = 0x0B;
internal const byte Short = 0x0C;
internal const byte UShort = 0x0D;
internal const byte String = 0x0E;
internal const byte ByteArray = 0x0F;
internal const byte CharArray = 0x10;
internal const byte Null = 0x11;
internal const byte Type = 0x12;
internal const byte Guid = 0x13;
internal const byte DateTime = 0x14;
internal const byte CompressedByteArray = 0x20;
internal const byte CompressedCharArray = 0x21;
internal const byte CompressedString = 0x22;
internal const byte CompressedUnknown = 0x23;
internal const byte ArrayBool = 0x41;
internal const byte ArraySByte = 0x43;
internal const byte ArrayDecimal = 0x45;
internal const byte ArrayDouble = 0x46;
internal const byte ArrayFloat = 0x47;
internal const byte ArrayInt = 0x48;
internal const byte ArrayUInt = 0x49;
internal const byte ArrayLong = 0x4A;
internal const byte ArrayULong = 0x4B;
internal const byte ArrayShort = 0x4C;
internal const byte ArrayUShort = 0x4D;
internal const byte ArrayString = 0x4E;
internal const byte ArrayType = 0x52;
internal const byte ArrayGuid = 0x53;
internal const byte ArrayDateTime = 0x54;
}
}
================================================
FILE: src/ServiceWire/PooledDictionary.cs
================================================
using System;
using System.Collections.Concurrent;
namespace ServiceWire
{
public sealed class PooledDictionary<TKey, TValue> : IDisposable
{
private readonly ConcurrentDictionary<TKey, ConcurrentQueue<TValue>> _dq;
private readonly int _concurrencyLevel;
private readonly int _size;
public PooledDictionary()
{
_concurrencyLevel = Environment.ProcessorCount * 8;
_size = _concurrencyLevel * _concurrencyLevel;
_dq = new ConcurrentDictionary<TKey, ConcurrentQueue<TValue>>(_concurrencyLevel, _size);
}
public void Add(TKey key, TValue value)
{
if (!_dq.ContainsKey(key)) _dq.TryAdd(key, new ConcurrentQueue<TValue>());
ConcurrentQueue<TValue> q;
if (_dq.TryGetValue(key, out q))
{
q.Enqueue(value);
}
else
{
throw new ArgumentException("Unable to add value");
}
}
public int Count(TKey key)
{
if (!_dq.ContainsKey(key)) _dq.TryAdd(key, new ConcurrentQueue<TValue>());
ConcurrentQueue<TValue> q;
if (_dq.TryGetValue(key, out q))
{
return q.Count;
}
return 0;
}
public TValue Request(TKey key, Func<TValue> creator = null)
{
if (!_dq.ContainsKey(key)) _dq.TryAdd(key, new ConcurrentQueue<TValue>());
ConcurrentQueue<TValue> q;
if (_dq.TryGetValue(key, out q))
{
TValue v;
if (q.TryDequeue(out v)) return v;
if (null != creator) return creator();
}
return default(TValue);
}
public void Release(TKey key, TValue value)
{
Add(key, value); //just adds it back to key's queue
}
#region IDisposable Members
private bool _disposed = false;
public void Dispose()
{
//MS recommended dispose pattern - prevents GC from disposing again
if (!_disposed)
{
_disposed = true;
foreach(var kvp in _dq)
{
while (!kvp.Value.IsEmpty)
{
TValue v;
if (kvp.Value.TryDequeue(out v))
{
var disp = v as IDisposable;
if (null != disp) disp.Dispose();
}
}
}
GC.SuppressFinalize(this);
}
}
#endregion
}
}
================================================
FILE: src/ServiceWire/ProxyBuilder.cs
================================================
using System;
using System.Reflection.Emit;
namespace ServiceWire
{
internal sealed class ProxyBuilder
{
public string ProxyName { get; set; }
public Type InterfaceType { get; set; }
public Type CtorType { get; set; }
public AssemblyBuilder AssemblyBuilder { get; set; }
public ModuleBuilder ModuleBuilder { get; set; }
public TypeBuilder TypeBuilder { get; set; }
}
}
================================================
FILE: src/ServiceWire/ProxyFactory.cs
================================================
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
namespace ServiceWire
{
public static class ProxyFactory
{
private const string PROXY_ASSEMBLY = "ProxyAssembly";
private const string INVOKE_METHOD = "InvokeMethod";
private const string PROXY_MODULE = "ProxyModule";
private const string PROXY = "Proxy";
//pooled dictionary achieves same or better performance as ThreadStatic without creating as many builders under average load
private static PooledDictionary<string, ProxyBuilder> _proxies = new PooledDictionary<string, ProxyBuilder>();
public static TInterface CreateProxy<TInterface>(Type channelType, Type ctorArgType, object channelCtorValue, ISerializer serializer, ICompressor compressor, ILog logger, IStats stats) where TInterface : class
{
if (!channelType.InheritsFrom(typeof(Channel))) throw new ArgumentException("channelType does not inherit from Channel");
Type interfaceType = typeof(TInterface);
//derive unique key for this dynamic assembly by interface, channel and ctor type names
var proxyName = interfaceType.ToConfigName() + channelType.ToConfigName() + ctorArgType.ToConfigName();
//get pooled proxy builder
var localChannelType = channelType;
var localCtorArgType = ctorArgType;
ProxyBuilder proxyBuilder = null;
TInterface proxy = null;
try
{
proxyBuilder = _proxies.Request(proxyName, () => CreateProxyBuilder(proxyName, interfaceType, localChannelType, localCtorArgType));
proxy = CreateProxy<TInterface>(proxyBuilder, channelCtorValue, serializer, compressor, logger, stats);
}
finally
{
//return builder to the pool
if (null != proxyBuilder) _proxies.Release(proxyName, proxyBuilder);
}
return proxy;
}
private static TInterface CreateProxy<TInterface>(ProxyBuilder proxyBuilder, object channelCtorValue, ISerializer serializer, ICompressor compressor, ILog logger, IStats stats) where TInterface : class
{
//create the type and construct an instance
Type[] ctorArgTypes = new Type[] { typeof(Type), proxyBuilder.CtorType, typeof(ISerializer), typeof(ICompressor), typeof(ILog), typeof(IStats) };
Type t = proxyBuilder.TypeBuilder.CreateTypeInfo();
var constructorInfo = t.GetConstructor(ctorArgTypes);
if (constructorInfo != null)
{
TInterface instance = (TInterface)constructorInfo.Invoke(new object[] { typeof(TInterface), channelCtorValue, serializer, compressor, logger, stats });
return instance;
}
return null;
}
private static ProxyBuilder CreateProxyBuilder(string proxyName, Type interfaceType, Type channelType, Type ctorArgType)
{
AppDomain domain = Thread.GetDomain();
// create a new assembly for the proxy
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(PROXY_ASSEMBLY), AssemblyBuilderAccess.Run);
// create a new module for the proxy
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(PROXY_MODULE);
// Set the class to be public and sealed
TypeAttributes typeAttributes = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;
// Construct the type builder
TypeBuilder typeBuilder = moduleBuilder.DefineType(interfaceType.Name + PROXY, typeAttributes, channelType);
List<Type> allInterfaces = new List<Type>(interfaceType.GetInterfaces());
allInterfaces.Add(interfaceType);
//add the interface
typeBuilder.AddInterfaceImplementation(interfaceType);
//construct the constructor
Type[] ctorArgTypes = new Type[] { typeof(Type), ctorArgType, typeof(ISerializer), typeof(ICompressor), typeof(ILog), typeof(IStats) };
CreateConstructor(channelType, typeBuilder, ctorArgTypes);
//construct the type maps
Dictionary<Type, OpCode> ldindOpCodeTypeMap = new Dictionary<Type, OpCode>();
ldindOpCodeTypeMap.Add(typeof(Boolean), OpCodes.Ldind_I1);
ldindOpCodeTypeMap.Add(typeof(Byte), OpCodes.Ldind_U1);
ldindOpCodeTypeMap.Add(typeof(SByte), OpCodes.Ldind_I1);
ldindOpCodeTypeMap.Add(typeof(Int16), OpCodes.Ldind_I2);
ldindOpCodeTypeMap.Add(typeof(UInt16), OpCodes.Ldind_U2);
ldindOpCodeTypeMap.Add(typeof(Int32), OpCodes.Ldind_I4);
ldindOpCodeTypeMap.Add(typeof(UInt32), OpCodes.Ldind_U4);
ldindOpCodeTypeMap.Add(typeof(Int64), OpCodes.Ldind_I8);
ldindOpCodeTypeMap.Add(typeof(UInt64), OpCodes.Ldind_I8);
ldindOpCodeTypeMap.Add(typeof(Char), OpCodes.Ldind_U2);
ldindOpCodeTypeMap.Add(typeof(Double), OpCodes.Ldind_R8);
ldindOpCodeTypeMap.Add(typeof(Single), OpCodes.Ldind_R4);
Dictionary<Type, OpCode> stindOpCodeTypeMap = new Dictionary<Type, OpCode>();
stindOpCodeTypeMap.Add(typeof(Boolean), OpCodes.Stind_I1);
stindOpCodeTypeMap.Add(typeof(Byte), OpCodes.Stind_I1);
stindOpCodeTypeMap.Add(typeof(SByte), OpCodes.Stind_I1);
stindOpCodeTypeMap.Add(typeof(Int16), OpCodes.Stind_I2);
stindOpCodeTypeMap.Add(typeof(UInt16), OpCodes.Stind_I2);
stindOpCodeTypeMap.Add(typeof(Int32), OpCodes.Stind_I4);
stindOpCodeTypeMap.Add(typeof(UInt32), OpCodes.Stind_I4);
stindOpCodeTypeMap.Add(typeof(Int64), OpCodes.Stind_I8);
stindOpCodeTypeMap.Add(typeof(UInt64), OpCodes.Stind_I8);
stindOpCodeTypeMap.Add(typeof(Char), OpCodes.Stind_I2);
stindOpCodeTypeMap.Add(typeof(Double), OpCodes.Stind_R8);
stindOpCodeTypeMap.Add(typeof(Single), OpCodes.Stind_R4);
//construct the method builders from the method infos defined in the interface
List<MethodInfo> methods = GetAllMethods(allInterfaces);
foreach (MethodInfo methodInfo in methods)
{
MethodBuilder methodBuilder = ConstructMethod(channelType, methodInfo, typeBuilder, ldindOpCodeTypeMap, stindOpCodeTypeMap);
typeBuilder.DefineMethodOverride(methodBuilder, methodInfo);
}
//create proxy builder
var result = new ProxyBuilder
{
ProxyName = proxyName,
InterfaceType = interfaceType,
CtorType = ctorArgType,
AssemblyBuilder = assemblyBuilder,
ModuleBuilder = moduleBuilder,
TypeBuilder = typeBuilder
};
return result;
}
private static List<MethodInfo> GetAllMethods(List<Type> allInterfaces)
{
List<MethodInfo> methods = new List<MethodInfo>();
foreach (Type interfaceType in allInterfaces)
methods.AddRange(interfaceType.GetMethods());
return methods;
}
private static void CreateConstructor(Type channelType, TypeBuilder typeBuilder, Type[] ctorArgTypes)
{
ConstructorBuilder ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, ctorArgTypes);
ConstructorInfo baseCtor = channelType.GetConstructor(ctorArgTypes);
ILGenerator ctorIL = ctor.GetILGenerator();
ctorIL.Emit(OpCodes.Ldarg_0); //load "this"
ctorIL.Emit(OpCodes.Ldarg_1); //load serviceType
ctorIL.Emit(OpCodes.Ldarg_2); //load "endpoint"
ctorIL.Emit(OpCodes.Ldarg_3); //load "serializer"
ctorIL.Emit(OpCodes.Ldarg_S, 4); //load "compressor"
ctorIL.Emit(OpCodes.Ldarg_S, 5); //load "logger"
ctorIL.Emit(OpCodes.Ldarg_S, 6); //load "stats"
ctorIL.Emit(OpCodes.Call, baseCtor); //call "base(...)"
ctorIL.Emit(OpCodes.Ret);
}
private static MethodBuilder ConstructMethod(Type channelType, MethodInfo methodInfo, TypeBuilder typeBuilder, Dictionary<Type, OpCode> ldindOpCodeTypeMap, Dictionary<Type, OpCode> stindOpCodeTypeMap)
{
ParameterInfo[] paramInfos = methodInfo.GetParameters();
int nofParams = paramInfos.Length;
Type[] parameterTypes = new Type[nofParams];
for (int i = 0; i < nofParams; i++) parameterTypes[i] = paramInfos[i].ParameterType;
Type returnType = methodInfo.ReturnType;
MethodBuilder methodBuilder = typeBuilder.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, returnType, parameterTypes);
ILGenerator mIL = methodBuilder.GetILGenerator();
GenerateILCodeForMethod(channelType, methodInfo, mIL, parameterTypes, methodBuilder.ReturnType, ldindOpCodeTypeMap, stindOpCodeTypeMap);
return methodBuilder;
}
private static void GenerateILCodeForMethod(Type channelType, MethodInfo methodInfo, ILGenerator mIL, Type[] inputArgTypes, Type returnType, Dictionary<Type, OpCode> ldindOpCodeTypeMap, Dictionary<Type, OpCode> stindOpCodeTypeMap)
{
mIL.Emit(OpCodes.Ldarg_0); //load "this"
int nofArgs = inputArgTypes.Length;
//get the MethodInfo for InvokeMethod
MethodInfo invokeMethodMI = channelType.GetMethod(INVOKE_METHOD, BindingFlags.Instance | BindingFlags.NonPublic);
//declare local variables
LocalBuilder resultLB = mIL.DeclareLocal(typeof(object[])); // object[] result
//set local value with method name and arg types to improve perfmance
//metadata: methodInfo.Name | inputTypes[x].FullName .. |
var metadata = methodInfo.Name;
if (inputArgTypes.Length > 0)
{
var args = new string[inputArgTypes.Length];
for (int i = 0; i < inputArgTypes.Length; i++) args[i] = inputArgTypes[i].ToConfigName();
metadata += "|" + string.Join("|", args);
}
//declare and assign string literal
LocalBuilder metaLB = mIL.DeclareLocal(typeof(string));
//mIL.Emit(OpCodes.Dup); //causes InvalidProgramException - Common Language Runtime detected an invalid program.
mIL.Emit(OpCodes.Ldstr, metadata);
mIL.Emit(OpCodes.Stloc_1); //load into metaData local variable
//load metadata into first param for invokeMethodMI
//mIL.Emit(OpCodes.Dup); //causes InvalidProgramException - Common Language Runtime detected an invalid program.
mIL.Emit(OpCodes.Ldloc_1);
mIL.Emit(OpCodes.Ldc_I4, nofArgs); //push the number of arguments
mIL.Emit(OpCodes.Newarr, typeof(object)); //create an array of objects
//store every input argument in the args array
for (int i = 0; i < nofArgs; i++)
{
Type inputType = inputArgTypes[i].IsByRef ? inputArgTypes[i].GetElementType() : inputArgTypes[i];
mIL.Emit(OpCodes.Dup);
mIL.Emit(OpCodes.Ldc_I4, i); //push the index onto the stack
mIL.Emit(OpCodes.Ldarg, i + 1); //load the i'th argument. This might be an address
if (inputArgTypes[i].IsByRef)
{
if (inputType.IsValueType)
{
if (inputType.IsPrimitive)
{
mIL.Emit(ldindOpCodeTypeMap[inputType]);
mIL.Emit(OpCodes.Box, inputType);
} else if (inputType.IsEnum && ldindOpCodeTypeMap.ContainsKey(Enum.GetUnderlyingType(inputType)))
{
//enum with a supported underlying type is converted to that underlying type
Type underlyingTypeEnum = Enum.GetUnderlyingType(inputType);
mIL.Emit(ldindOpCodeTypeMap[underlyingTypeEnum]);
mIL.Emit(OpCodes.Box, inputType);
} else
{
throw new NotSupportedException("Non-primitive native types (e.g. Decimal and Guid) ByRef are not supported.");
}
} else
{
mIL.Emit(OpCodes.Ldind_Ref);
}
} else
{
if (inputArgTypes[i].IsValueType)
mIL.Emit(OpCodes.Box, inputArgTypes[i]);
}
mIL.Emit(OpCodes.Stelem_Ref); //store the reference in the args array
}
mIL.Emit(OpCodes.Call, invokeMethodMI);
mIL.Emit(OpCodes.Stloc, resultLB.LocalIndex); //store the result
//store the results in the arguments
for (int i = 0; i < nofArgs; i++)
{
if (inputArgTypes[i].IsByRef)
{
Type inputType = inputArgTypes[i].GetElementType();
mIL.Emit(OpCodes.Ldarg, i + 1); //load the address of the argument
mIL.Emit(OpCodes.Ldloc, resultLB.LocalIndex); //load the result array
mIL.Emit(OpCodes.Ldc_I4, i + 1); //load the index into the result array
mIL.Emit(OpCodes.Ldelem_Ref); //load the value in the index of the array
if (inputType.IsEnum && ldindOpCodeTypeMap.ContainsKey(Enum.GetUnderlyingType(inputType)))
{
//enum with a supported underlying type is converted to that underlying type
Type underlyingTypeEnum = Enum.GetUnderlyingType(inputType);
mIL.Emit(OpCodes.Unbox, underlyingTypeEnum);
mIL.Emit(ldindOpCodeTypeMap[underlyingTypeEnum]);
mIL.Emit(stindOpCodeTypeMap[underlyingTypeEnum]);
} else if (inputType.IsValueType)
{
mIL.Emit(OpCodes.Unbox, inputArgTypes[i].GetElementType());
mIL.Emit(ldindOpCodeTypeMap[inputArgTypes[i].GetElementType()]);
mIL.Emit(stindOpCodeTypeMap[inputArgTypes[i].GetElementType()]);
} else
{
mIL.Emit(OpCodes.Castclass, inputArgTypes[i].GetElementType());
mIL.Emit(OpCodes.Stind_Ref); //store the unboxed value at the argument address
}
}
}
if (returnType != typeof(void))
{
mIL.Emit(OpCodes.Ldloc, resultLB.LocalIndex); //load the result array
mIL.Emit(OpCodes.Ldc_I4, 0); //load the index of the return value. Alway 0
mIL.Emit(OpCodes.Ldelem_Ref); //load the value in the index of the array
if (returnType.IsValueType)
{
mIL.Emit(OpCodes.Unbox, returnType); //unbox it
if (returnType.IsPrimitive) //deal with primitive vs struct value types
mIL.Emit(ldindOpCodeTypeMap[returnType]);
else
mIL.Emit(OpCodes.Ldobj, returnType);
} else
{
mIL.Emit(OpCodes.Castclass, returnType);
}
}
mIL.Emit(OpCodes.Ret);
}
}
}
================================================
FILE: src/ServiceWire/SerializationValidator.cs
================================================
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
namespace ServiceWire
{
internal static class SerializationValidator
{
public static List<string> NonSerializableTypes(this Type type)
{
var nonSerializableTypes = new List<string>();
AnalyzeType(type, nonSerializableTypes);
return nonSerializableTypes;
}
public static void ValidateServiceInterface(this Type type)
{
var nonSerializableTypes = new List<string>();
var methods = type.GetMethods(BindingFlags.Public);
foreach (var method in methods)
{
if (method.ReturnType != typeof (void))
{
AnalyzeType(method.ReturnType, nonSerializableTypes);
}
var parameters = method.GetParameters();
foreach (var parameter in parameters)
{
if (parameter.ParameterType.IsByRef)
{
Type inputType = parameter.ParameterType.GetElementType();
if (inputType.IsValueType && !inputType.IsPrimitive)
throw new NotSupportedException("Non-primitive native types (e.g. Decimal and Guid) ByRef are not supported.");
}
AnalyzeType(parameter.ParameterType, nonSerializableTypes);
}
}
if (nonSerializableTypes.Count > 0)
{
var errorMessage =
string.Format("One or more types in {0} are not marked with the Serializable attribute: {1}",
type.ToConfigName(), string.Join(",", nonSerializableTypes));
throw new SerializationException(errorMessage);
}
}
private static void AnalyzeType(Type type, List<string> nonSerializableTypes)
{
if (type.IsValueType || type == typeof(string)) return;
if (type.IsEnum)
{
//enum with a supported underlying type is converted to that underlying type
Type underlyingTypeEnum = Enum.GetUnderlyingType(type);
if (underlyingTypeEnum.IsValueType || underlyingTypeEnum == typeof(string)) return;
}
if (!IsSerializable(type))
nonSerializableTypes.Add(type.Name);
foreach (var propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
if (propertyInfo.PropertyType.IsGenericType)
{
foreach (var genericArgument in propertyInfo.PropertyType.GetGenericArguments())
{
if (genericArgument == type) continue; // base case for circularly referenced properties
AnalyzeType(genericArgument, nonSerializableTypes);
}
}
else if (propertyInfo.GetType() != type) // base case for circularly referenced properties
AnalyzeType(propertyInfo.PropertyType, nonSerializableTypes);
}
}
private static bool IsSerializable(Type type)
{
return (Attribute.IsDefined(type, typeof(SerializableAttribute)));
}
}
}
================================================
FILE: src/ServiceWire/ServiceInstance.cs
================================================
using System;
using System.Collections.Concurrent;
using System.Reflection;
namespace ServiceWire
{
public class ServiceInstance
{
public int KeyIndex { get; set; }
public Type InterfaceType { get; set; }
public object SingletonInstance { get; set; }
public ConcurrentDictionary<int, MethodInfo> InterfaceMethods { get; set; }
public ConcurrentDictionary<int, bool[]> MethodParametersByRef { get; set; }
public ServiceSyncInfo ServiceSyncInfo { get; set; }
}
}
================================================
FILE: src/ServiceWire/ServiceSyncInfo.cs
================================================
using System;
using System.Runtime.Serialization;
namespace ServiceWire
{
[Serializable, DataContract]
public class ServiceSyncInfo
{
[DataMember(Order = 1)]
public int ServiceKeyIndex { get; set; }
[DataMember(Order = 2)]
public MethodSyncInfo[] MethodInfos { get; set; }
[DataMember(Order = 3)]
public bool UseCompression { get; set; }
[DataMember(Order = 4)]
public int CompressionThreshold { get; set; }
}
}
================================================
FILE: src/ServiceWire/ServiceSyncInfoCacheKey.cs
================================================
using System;
namespace ServiceWire
{
internal class ServiceSyncInfoCacheKey : IEquatable<ServiceSyncInfoCacheKey>
{
public Type Type { get; }
public IChannelIdentifier ChannelIdentifier { get; }
public ServiceSyncInfoCacheKey(Type type, IChannelIdentifier channelIdentifier)
{
Type = type;
ChannelIdentifier = channelIdentifier;
}
public bool Equals(ServiceSyncInfoCacheKey other)
{
return Type.Equals(other.Type)
&& ChannelIdentifier.Equals(other.ChannelIdentifier);
}
public override bool Equals(object obj)
{
if (obj is ServiceSyncInfoCacheKey other)
{
return Equals(other);
}
return false;
}
public override int GetHashCode()
{
unchecked
{
return Type.GetHashCode() + ChannelIdentifier.GetHashCode();
}
}
}
}
================================================
FILE: src/ServiceWire/ServiceWire.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Tyler Jensen</Authors>
<Company />
<PackageIcon>icon.png</PackageIcon>
<PackageProjectUrl>https://github.com/tylerjensen/ServiceWire</PackageProjectUrl>
<PackageLicenseFile>License.txt</PackageLicenseFile>
<Copyright>Tyler Jensen 2013-2021</Copyright>
<Version>5.6.0</Version>
<Description>ServiceWire is a very fast and light weight service host and dynamic client library that simplifies the development and use of high performance remote procedure call (RPC) communication between .NET processes over Named Pipes or TCP/IP. And with the release of 2.0.0, ServiceWire now supports optional use of Zero Knowledge authentication with a fast variation of Secure Remote Password Protocol and strong Rijndael encryption of data across the wire via TCP without the need for public keys going across the wire.</Description>
<PackageTags>WCF Services Host Client NamedPipes TCP Messaging RPC Interception Zero Knowledge Secure Remote Password Protocol Serialization</PackageTags>
<PackageReleaseNotes>Contributions fix TCP client synchronous connection blocks and adds NamedPipeServerStreamFactory to allow greater level of permissions control in using named pipes. Multiple code improvements.</PackageReleaseNotes>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<None Include="..\License.txt" Pack="true" PackagePath="" />
<None Include="..\icon.png" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.IO.Pipes" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
<PackageReference Include="System.Text.Json" Version="9.0.0" />
<PackageReference Include="System.Threading" Version="4.3.0" />
</ItemGroup>
</Project>
================================================
FILE: src/ServiceWire/Stats.cs
================================================
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace ServiceWire
{
public class Stats : LoggerBase, IStats
{
private int _statsBufferSize = 10000;
private const string StatFilePrefixDefault = "stat-";
private const string StatFileExtensionDefault = ".txt";
public Stats(string statsDirectory = null,
string statsFilePrefix = null,
string statsFileExtension = null,
int messageBufferSize = 32,
int statsBufferSize = 10000,
LogOptions options = LogOptions.LogOnlyToFile,
LogRollOptions rollOptions = LogRollOptions.Daily,
int rollMaxMegaBytes = 1024,
bool useUtcTimeStamp = false)
{
_logDirectory = statsDirectory ?? Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "logs");
Directory.CreateDirectory(_logDirectory); //will throw if unable - does not throw if already exists
_logFilePrefix = statsFilePrefix ?? StatFilePrefixDefault;
_logFileExtension = statsFileExtension ?? StatFileExtensionDefault;
_messageBufferSize = messageBufferSize;
_statsBufferSize = statsBufferSize;
_rollOptions = rollOptions;
_rollMaxMegaBytes = rollMaxMegaBytes;
_useUtcTimeStamp = useUtcTimeStamp;
LogOptions = options;
if (_messageBufferSize < 1) _messageBufferSize = 1;
if (_messageBufferSize > 4096) _messageBufferSize = 4096;
if (_statsBufferSize < 10) _statsBufferSize = 10;
if (_statsBufferSize > 1000000) _statsBufferSize = 1000000;
if (_rollOptions == LogRollOptions.Size)
{
if (_rollMaxMegaBytes < 1) _rollMaxMegaBytes = 1;
if (_rollMaxMegaBytes < 4096) _rollMaxMegaBytes = 4096;
}
}
private void WriteLines(string[] lines)
{
_logQueue.Enqueue(lines);
if (_logQueue.Count >= _messageBufferSize)
Task.Factory.StartNew(() => WriteBuffer(_messageBufferSize));
}
public override void FlushLog()
{
var items = new List<string[]>();
foreach (var kvp in _bag)
{
items.Add(kvp.Value.GetDump());
}
foreach(var list in items) WriteLines(list);
base.FlushLog();
}
//period, cat, nm, count, total
private int _period = 0;
private ConcurrentDictionary<int, StatsBag> _bag = new ConcurrentDictionary<int, StatsBag>();
private void WriteBag(StatsBag bag)
{
int p = _period;
Interlocked.Increment(ref _period);
var lines = bag.GetDump();
StatsBag b;
if (_bag.TryRemove(p, out b)) b.Clear();
WriteLines(lines);
}
public void Log(string name, float value)
{
int p = _period;
var bag = _bag.GetOrAdd(p, new StatsBag(_useUtcTimeStamp));
bag.Add("unspecified", name, value);
if (bag.Count >= _statsBufferSize)
{
WriteBag(bag);
}
}
public void Log(string category, string name, float value)
{
int p = _period;
var bag = _bag.GetOrAdd(p, new StatsBag(_useUtcTimeStamp));
bag.Add(category, name, value);
if (bag.Count >= _statsBufferSize)
{
WriteBag(bag);
}
}
}
}
================================================
FILE: src/ServiceWire/StatsBag.cs
================================================
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace ServiceWire
{
internal class StatsBag
{
private bool _useUtcTime = false;
public StatsBag(bool useUtcTime)
{
_useUtcTime = useUtcTime;
_started = _useUtcTime ? DateTime.UtcNow : DateTime.Now;
}
private DateTime _started = DateTime.Now;
private int _count = 0;
private ConcurrentDictionary<string, ConcurrentDictionary<string, StatInfo>> _bag
= new ConcurrentDictionary<string, ConcurrentDictionary<string, StatInfo>>();
public int Count { get { return _count; } }
public void Clear()
{
_bag.Clear();
}
protected const string TimeStampPattern = "yyyy-MM-ddTHH:mm:ss.fff";
protected string GetTimeStamp()
{
return _useUtcTime
? DateTime.UtcNow.ToString(TimeStampPattern)
: DateTime.Now.ToString(TimeStampPattern);
}
protected string GetTimeStamp(DateTime dt)
{
return _useUtcTime
? dt.ToUniversalTime().ToString(TimeStampPattern)
: dt.ToString(TimeStampPattern);
}
public void Add(string category, string name, float value)
{
var val = value;
var container = _bag.GetOrAdd(category, new ConcurrentDictionary<string, StatInfo>());
container.AddOrUpdate(name, s => new StatInfo(val), (s, t) =>
{
t.Increment(val);
return t;
});
Interlocked.Increment(ref _count);
}
public string[] GetDump()
{
var dumped = _useUtcTime ? DateTime.UtcNow : DateTime.Now;
TimeSpan ts = dumped - _started;
var tsTxt = ts.TotalSeconds.ToString("######.000000");
var lines = new List<string>();
//add header
lines.Add(string.Format("<entry fr=\"{0}\" to=\"{1}\" cnt=\"{2}\" secs=\"{3}\">", GetTimeStamp(_started), GetTimeStamp(dumped), _count, tsTxt));
foreach (var cat in _bag)
{
var catCount = (from n in cat.Value select n.Value.Count).Sum();
lines.Add(string.Format(" <cat nm=\"{0}\" cnt=\"{1}\">", cat.Key, catCount));
foreach (var stat in cat.Value)
{
if (null == stat.Value) continue;
float total = stat.Value.Total;
float avg = total == 0.0f
? 0.0f
: total / stat.Value.Count;
lines.Add(string.Format(" <stat nm=\"{0}\" cnt=\"{1}\" tot=\"{2}\" avg=\"{3}\" />",
stat.Key, stat.Value.Count, total, avg));
}
lines.Add(" </cat>");
}
lines.Add("</entry>");
return lines.ToArray();
}
}
internal class StatInfo
{
private ConcurrentBag<float> _bag = new ConcurrentBag<float>();
public int Count
{
get { return _bag.Count; }
}
public float Total
{
get
{
return _bag.Sum();
}
}
public StatInfo(float value)
{
_bag.Add(value);
}
public void Increment(float value)
{
_bag.Add(value);
}
}
}
================================================
FILE: src/ServiceWire/StreamingChannel.cs
================================================
using ServiceWire.ZeroKnowledge;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Security.Authentication;
using System.Threading.Tasks;
namespace ServiceWire
{
public class StreamingChannel : Channel, IDvChannel
{
private readonly object _syncRoot = new object();
protected BinaryReader _binReader;
protected BinaryWriter _binWriter;
protected Stream _stream;
private readonly ParameterTransferHelper _parameterTransferHelper;
private ServiceSyncInfo _syncInfo;
private ZkCrypto _zkCrypto;
// keep cached sync info to avoid redundant wire trips
private static readonly ConcurrentDictionary<ServiceSyncInfoCacheKey, ServiceSyncInfo> SyncInfoCache = new ConcurrentDictionary<ServiceSyncInfoCacheKey, ServiceSyncInfo>();
public StreamingChannel(ISerializer serializer, ICompressor compressor, ILog logger = null, IStats stats = null)
: base(serializer, compressor, logger, stats)
{
_parameterTransferHelper = new ParameterTransferHelper(_serializer, _compressor);
}
public static void ClearCachedSyncInfo()
{
SyncInfoCache.Clear();
}
protected virtual IChannelIdentifier ChannelIdentifier { get; }
/// <summary>
/// Returns true if client is connected to the server.
/// </summary>
public virtual bool IsConnected => false;
/// <summary>
/// This method asks the server for a list of identifiers paired with method
/// names and -parameter types. This is used when invoking methods server side.
/// </summary>
protected override void SyncInterface(Type serviceType,
string username = null, string password = null)
{
if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
{
var sw = Stopwatch.StartNew();
_logger.Debug("Zk authentiation started for: {0}, {1}", username, password);
//do zk protocol authentication
var sr = new ZkProtocol();
// Step 1. Client sends username and ephemeral hash of random number.
var aRand = sr.CryptRand();
var aClientEphemeral = sr.GetClientEphemeralA(aRand);
// send username and aClientEphemeral to server
_binWriter.Write((int)MessageType.ZkInitiate);
_binWriter.Write(username);
_logger.Debug("username sent to server: {0}", username);
_binWriter.Write(aClientEphemeral); //always 32 bytes
_logger.Debug("ClientEphemeral (A) sent to server: {0}", Convert.ToBase64String(aClientEphemeral));
// get response from server
var userFound = _binReader.ReadBoolean();
if (!userFound)
{
_logger.Debu
gitextract_ub_i6dpw/
├── .gitattributes
├── .github/
│ └── workflows/
│ └── build-and-test.yml
├── .gitignore
├── README.md
└── src/
├── Benchmarks/
│ └── ServiceWire.Benchmarks/
│ ├── ConnectionBenchmarks.cs
│ ├── INetTester.cs
│ ├── NamedPipesBenchmarks.cs
│ ├── NewtonSoftSerializer.cs
│ ├── Program.cs
│ ├── ServiceWire.Benchmarks.csproj
│ └── TcpBenchmarks.cs
├── Demo/
│ ├── DemoClient/
│ │ ├── App.config
│ │ ├── DemoClient.csproj
│ │ └── Program.cs
│ ├── DemoCommon/
│ │ ├── Contracts.cs
│ │ └── DemoCommon.csproj
│ └── DemoHost/
│ ├── App.config
│ ├── DemoHost.csproj
│ └── Program.cs
├── License.txt
├── Serializers/
│ └── ServiceWire.Serializers/
│ ├── BinaryFormatterSerializer.cs
│ └── ServiceWire.Serializers.csproj
├── ServiceWire/
│ ├── Aspects/
│ │ ├── CrossCuttingConcerns.cs
│ │ ├── InterceptChannel.cs
│ │ ├── InterceptPoint.cs
│ │ └── Interceptor.cs
│ ├── Channel.cs
│ ├── DefaultCompressor.cs
│ ├── DefaultSerializer.cs
│ ├── DefaultTypeMaker.cs
│ ├── Host.cs
│ ├── IChannelIdentifier.cs
│ ├── ICompressor.cs
│ ├── IDvChannel.cs
│ ├── ILog.cs
│ ├── ISerializer.cs
│ ├── IStats.cs
│ ├── LogLevel.cs
│ ├── LogOptions.cs
│ ├── LogRollOptions.cs
│ ├── Logger.cs
│ ├── LoggerBase.cs
│ ├── MemoryDetail.cs
│ ├── MessageType.cs
│ ├── MethodSyncInfo.cs
│ ├── NamedPipes/
│ │ ├── DefaultNamedPipeServerStreamFactory.cs
│ │ ├── INamedPipeServerStreamFactory.cs
│ │ ├── NpChannel.cs
│ │ ├── NpChannelIdentifier.cs
│ │ ├── NpClient.cs
│ │ ├── NpEndPoint.cs
│ │ ├── NpHost.cs
│ │ ├── NpListener.cs
│ │ ├── NpProxy.cs
│ │ ├── PipeClientConnectionEventArgs.cs
│ │ ├── ReadFileToStream.cs
│ │ └── StreamString.cs
│ ├── NetExtensions.cs
│ ├── NullLogger.cs
│ ├── NullStats.cs
│ ├── ParameterTransferHelper.cs
│ ├── ParameterTypes.cs
│ ├── PooledDictionary.cs
│ ├── ProxyBuilder.cs
│ ├── ProxyFactory.cs
│ ├── SerializationValidator.cs
│ ├── ServiceInstance.cs
│ ├── ServiceSyncInfo.cs
│ ├── ServiceSyncInfoCacheKey.cs
│ ├── ServiceWire.csproj
│ ├── Stats.cs
│ ├── StatsBag.cs
│ ├── StreamingChannel.cs
│ ├── TcpIp/
│ │ ├── TcpChannel.cs
│ │ ├── TcpChannelIdentifier.cs
│ │ ├── TcpClient.cs
│ │ ├── TcpEndPoint.cs
│ │ ├── TcpHost.cs
│ │ ├── TcpProxy.cs
│ │ └── TcpZkEndPoint.cs
│ ├── ZeroKnowledge/
│ │ ├── IZkRepository.cs
│ │ ├── ZkBigInt.cs
│ │ ├── ZkCrypto.cs
│ │ ├── ZkExt.cs
│ │ ├── ZkPasswordHash.cs
│ │ ├── ZkProtocol.cs
│ │ ├── ZkSafePrimes.cs
│ │ └── ZkSession.cs
│ └── _license.txt
├── ServiceWire.sln
├── ServiceWireTestHostPlusClient/
│ ├── Program.cs
│ └── ServiceWireTestHostPlusClient.csproj
├── Tests/
│ ├── Integration/
│ │ ├── ServiceWireTestClient1/
│ │ │ ├── App.config
│ │ │ ├── Program.cs
│ │ │ └── ServiceWireTestClient1.csproj
│ │ ├── ServiceWireTestClient2/
│ │ │ ├── App.config
│ │ │ ├── Program.cs
│ │ │ └── ServiceWireTestClient2.csproj
│ │ └── ServiceWireTestHost/
│ │ ├── App.config
│ │ ├── Program.cs
│ │ └── ServiceWireTestHost.csproj
│ ├── ServiceWireTestCommon/
│ │ ├── ServiceWireTestCommon.csproj
│ │ └── TestContracts.cs
│ ├── Unit/
│ │ └── ServiceWireTests/
│ │ ├── AsyncTests.cs
│ │ ├── INetTester.cs
│ │ ├── InterceptionTests.cs
│ │ ├── NewtonsoftSerializer.cs
│ │ ├── NpTests.cs
│ │ ├── ParameterTransferHelperTests.cs
│ │ ├── ProtobufSerializer.cs
│ │ ├── SequentialCollection.cs
│ │ ├── ServiceWireTests.csproj
│ │ ├── TcpTests.cs
│ │ ├── TcpZkTests.cs
│ │ └── ZkProtocolTests.cs
│ └── testing_readme.txt
└── output.txt
SYMBOL INDEX (606 symbols across 91 files)
FILE: src/Benchmarks/ServiceWire.Benchmarks/ConnectionBenchmarks.cs
class ConnectionBenchmarks (line 10) | [SimpleJob(RuntimeMoniker.Net80, baseline: true)]
method CreateTcpEndPoint (line 25) | private IPEndPoint CreateTcpEndPoint(int portOffset)
method CreateNpEndPoint (line 30) | private NpEndPoint CreateNpEndPoint(string offset)
method ConnectionBenchmarks (line 35) | public ConnectionBenchmarks()
method TcpConn (line 42) | [Benchmark]
method NpConn (line 58) | [Benchmark]
FILE: src/Benchmarks/ServiceWire.Benchmarks/INetTester.cs
type INetTester (line 8) | public interface INetTester
method Min (line 10) | int Min(int a, int b);
method Range (line 11) | Dictionary<int, int> Range(int start, int count);
method Get (line 12) | TestResponse Get(Guid id, string label, double weight, out int quantity);
method CalculateAsync (line 13) | Task<int> CalculateAsync(int a, int b);
type TestResponse (line 16) | [Serializable]
class NetTester (line 25) | public class NetTester : INetTester
method Min (line 27) | public int Min(int a, int b)
method Range (line 32) | public Dictionary<int, int> Range(int start, int count)
method CalculateAsync (line 37) | public Task<int> CalculateAsync(int a, int b)
method Get (line 42) | public TestResponse Get(Guid id, string label, double weight, out int ...
FILE: src/Benchmarks/ServiceWire.Benchmarks/NamedPipesBenchmarks.cs
class NamedPipesBenchmarks (line 8) | [SimpleJob(RuntimeMoniker.Net80, baseline: true)]
method CreateNpEndPoint (line 24) | private NpEndPoint CreateNpEndPoint(string offset)
method NamedPipesBenchmarks (line 29) | public NamedPipesBenchmarks()
method GlobalSetup (line 43) | [GlobalSetup]
method GlobalCleanup (line 50) | [GlobalCleanup]
method NpSim (line 59) | [Benchmark]
method NpSimJson (line 67) | [Benchmark]
method NpRg (line 75) | [Benchmark]
method NpRgJson (line 86) | [Benchmark]
method NpCxOut (line 97) | [Benchmark]
method NpCxOutJson (line 104) | [Benchmark]
FILE: src/Benchmarks/ServiceWire.Benchmarks/NewtonSoftSerializer.cs
class NewtonsoftSerializer (line 7) | public class NewtonsoftSerializer : ISerializer
method Deserialize (line 14) | public T Deserialize<T>(byte[] bytes)
method Deserialize (line 21) | public object Deserialize(byte[] bytes, string typeConfigName)
method Serialize (line 30) | public byte[] Serialize<T>(T obj)
method Serialize (line 37) | public byte[] Serialize(object obj, string typeConfigName)
FILE: src/Benchmarks/ServiceWire.Benchmarks/Program.cs
class Program (line 8) | public class Program
method Main (line 10) | public static void Main(string[] args)
method OpenUrl (line 35) | private static void OpenUrl(string url)
FILE: src/Benchmarks/ServiceWire.Benchmarks/TcpBenchmarks.cs
class TcpBenchmarks (line 9) | [SimpleJob(RuntimeMoniker.Net80, baseline: true)]
method CreateTcpEndPoint (line 27) | private IPEndPoint CreateTcpEndPoint(int portOffset)
method TcpBenchmarks (line 32) | public TcpBenchmarks()
method GlobalSetup (line 46) | [GlobalSetup]
method GlobalCleanup (line 53) | [GlobalCleanup]
method TcpSim (line 62) | [Benchmark]
method TcpSimJson (line 70) | [Benchmark]
method TcpRg (line 78) | [Benchmark]
method TcpRgJson (line 89) | [Benchmark]
method TcpCxOut (line 100) | [Benchmark]
method TcpCxOutJson (line 107) | [Benchmark]
FILE: src/Demo/DemoClient/Program.cs
class Program (line 13) | class Program
method Main (line 15) | private static async Task Main(string[] args)
method RunTest (line 44) | private static async Task RunTest(IPEndPoint zkEndpoint, string ip, Lo...
method RunTest (line 82) | private static async Task RunTest(TcpZkEndPoint zkEndpoint, string ip,...
FILE: src/Demo/DemoCommon/Contracts.cs
type ITest (line 7) | public interface ITest
method SetAsync (line 9) | Task SetAsync(int a);
method GetAsync (line 10) | Task<int> GetAsync();
type IDataContract (line 13) | public interface IDataContract
method GetDecimal (line 15) | decimal GetDecimal(decimal input);
method OutDecimal (line 16) | bool OutDecimal(decimal val);
type IIPCBridge (line 18) | public interface IIPCBridge
method GetData (line 20) | List<float> GetData();
type IComplexDataContract (line 23) | public interface IComplexDataContract
method GetId (line 25) | Guid GetId(string source, double weight, int quantity, DateTime dt);
method Get (line 26) | ComplexResponse Get(Guid id, string label, double weight, out long qua...
method TestLong (line 27) | long TestLong(out long id1, out long id2);
method GetItems (line 28) | List<string> GetItems(Guid id);
type ComplexResponse (line 31) | [Serializable]
FILE: src/Demo/DemoHost/Program.cs
class Program (line 14) | class Program
method Main (line 16) | static void Main(string[] args)
class IPCBridge (line 66) | public class IPCBridge : IIPCBridge
method GetData (line 68) | public List<float> GetData()
class Test (line 76) | public class Test : ITest
method SetAsync (line 78) | public Task SetAsync(int a)
method GetAsync (line 83) | public Task<int> GetAsync()
class DataContractImpl (line 89) | public class DataContractImpl : IDataContract
method GetDecimal (line 91) | public decimal GetDecimal(decimal input)
method OutDecimal (line 96) | public bool OutDecimal(decimal val)
class ComplexDataContractImpl (line 103) | public class ComplexDataContractImpl : IComplexDataContract
method GetId (line 105) | public Guid GetId(string source, double weight, int quantity, DateTime...
method Get (line 110) | public ComplexResponse Get(Guid id, string label, double weight, out l...
method GetItems (line 116) | public List<string> GetItems(Guid id)
method TestLong (line 125) | public long TestLong(out long id1, out long id2)
class DemoZkRepository (line 133) | public class DemoZkRepository : IZkRepository
method GetPasswordHashSet (line 139) | public ZkPasswordHash GetPasswordHashSet(string username)
FILE: src/Serializers/ServiceWire.Serializers/BinaryFormatterSerializer.cs
class BinaryFormatterSerializer (line 8) | public class BinaryFormatterSerializer : ISerializer
method Serialize (line 12) | public byte[] Serialize<T>(T obj)
method Serialize (line 22) | public byte[] Serialize(object obj, string typeConfigName)
method Deserialize (line 34) | public T Deserialize<T>(byte[] bytes)
method Deserialize (line 43) | public object Deserialize(byte[] bytes, string typeConfigName)
FILE: src/ServiceWire/Aspects/CrossCuttingConcerns.cs
class CrossCuttingConcerns (line 5) | public class CrossCuttingConcerns
FILE: src/ServiceWire/Aspects/InterceptChannel.cs
class InterceptChannel (line 8) | public class InterceptChannel : Channel
method InterceptChannel (line 15) | public InterceptChannel(Type interceptedType, InterceptPoint intercept...
method SyncInterface (line 24) | protected override void SyncInterface(Type interceptedType,
method CreateMethodMap (line 34) | private void CreateMethodMap()
method InvokeMethod (line 104) | protected override object[] InvokeMethod(string metaData, params objec...
method Dispose (line 211) | protected override void Dispose(bool disposing)
FILE: src/ServiceWire/Aspects/InterceptPoint.cs
class InterceptPoint (line 3) | public class InterceptPoint
FILE: src/ServiceWire/Aspects/Interceptor.cs
class Interceptor (line 5) | public static class Interceptor
method Intercept (line 7) | public static TTarget Intercept<TTarget>(TTarget target, CrossCuttingC...
method Intercept (line 12) | public static TTarget Intercept<TTarget>(int id, TTarget target, Cross...
FILE: src/ServiceWire/Channel.cs
class Channel (line 5) | public abstract class Channel : IDisposable
method Channel (line 14) | public Channel(ISerializer serializer, ICompressor compressor, ILog lo...
method InjectLoggerStats (line 22) | [Obsolete]
method InvokeMethod (line 35) | protected abstract object[] InvokeMethod(string metaData, params objec...
method SyncInterface (line 43) | protected abstract void SyncInterface(Type serviceType,
method Dispose (line 50) | public void Dispose()
method Dispose (line 57) | protected abstract void Dispose(bool disposing);
FILE: src/ServiceWire/DefaultCompressor.cs
class DefaultCompressor (line 6) | public class DefaultCompressor : ICompressor
method Compress (line 8) | public byte[] Compress(byte[] data)
method DeCompress (line 22) | public byte[] DeCompress(byte[] compressedBytes)
FILE: src/ServiceWire/DefaultSerializer.cs
class DefaultSerializer (line 7) | public class DefaultSerializer : ISerializer
method Serialize (line 9) | public byte[] Serialize<T>(T obj)
method Serialize (line 15) | public byte[] Serialize(object obj, string typeConfigName)
method Deserialize (line 21) | public T Deserialize<T>(byte[] bytes)
method Deserialize (line 27) | public object Deserialize(byte[] bytes, string typeConfigName)
FILE: src/ServiceWire/DefaultTypeMaker.cs
class DefaultTypeMaker (line 5) | internal class DefaultTypeMaker
method GetDefault (line 7) | public object GetDefault(Type t)
method GetDefaultGeneric (line 12) | public T GetDefaultGeneric<T>()
FILE: src/ServiceWire/Host.cs
class Host (line 12) | public abstract class Host : IDisposable
method Host (line 29) | public Host(ISerializer serializer, ICompressor compressor)
method AddService (line 128) | public void AddService<TService>(TService service) where TService : class
method CreateMethodMap (line 154) | private ServiceInstance CreateMethodMap(int keyIndex, Type serviceType...
method Open (line 229) | public void Open()
method StartListener (line 235) | protected abstract void StartListener();
method Close (line 240) | public void Close()
method ProcessRequest (line 245) | protected void ProcessRequest(Stream stream)
method ProcessRequest (line 261) | protected virtual void ProcessRequest(Stream readStream, Stream writeS...
method ProcessSync (line 322) | private void ProcessSync(ZkSession session, BinaryReader binReader, Bi...
method ProcessInvocation (line 385) | private void ProcessInvocation(ZkSession session, BinaryReader binRead...
method Dispose (line 499) | public void Dispose()
method Dispose (line 506) | protected virtual void Dispose(bool disposing)
FILE: src/ServiceWire/IChannelIdentifier.cs
type IChannelIdentifier (line 3) | public interface IChannelIdentifier
FILE: src/ServiceWire/ICompressor.cs
type ICompressor (line 3) | public interface ICompressor
method Compress (line 5) | byte[] Compress(byte[] data);
method DeCompress (line 6) | byte[] DeCompress(byte[] compressedBytes);
FILE: src/ServiceWire/IDvChannel.cs
type IDvChannel (line 6) | public interface IDvChannel
FILE: src/ServiceWire/ILog.cs
type ILog (line 3) | public interface ILog
method Debug (line 5) | void Debug(string formattedMessage, params object[] args);
method Info (line 6) | void Info(string formattedMessage, params object[] args);
method Warn (line 7) | void Warn(string formattedMessage, params object[] args);
method Error (line 8) | void Error(string formattedMessage, params object[] args);
method Fatal (line 9) | void Fatal(string formattedMessage, params object[] args);
FILE: src/ServiceWire/ISerializer.cs
type ISerializer (line 3) | public interface ISerializer
method Serialize (line 5) | byte[] Serialize<T>(T obj);
method Serialize (line 6) | byte[] Serialize(object obj, string typeConfigName);
method Deserialize (line 7) | T Deserialize<T>(byte[] bytes);
method Deserialize (line 8) | object Deserialize(byte[] bytes, string typeConfigName);
FILE: src/ServiceWire/IStats.cs
type IStats (line 3) | public interface IStats
method Log (line 5) | void Log(string name, float value);
method Log (line 6) | void Log(string category, string name, float value);
FILE: src/ServiceWire/LogLevel.cs
type LogLevel (line 3) | public enum LogLevel
FILE: src/ServiceWire/LogOptions.cs
type LogOptions (line 3) | public enum LogOptions
FILE: src/ServiceWire/LogRollOptions.cs
type LogRollOptions (line 3) | public enum LogRollOptions
FILE: src/ServiceWire/Logger.cs
class Logger (line 7) | public class Logger : LoggerBase, ILog
method Logger (line 24) | public Logger(string logDirectory = null,
method WriteMessage (line 54) | private void WriteMessage(LogLevel logLevel, string formattedMessage, ...
method Debug (line 68) | public void Debug(string formattedMessage, params object[] args)
method Info (line 73) | public void Info(string formattedMessage, params object[] args)
method Warn (line 78) | public void Warn(string formattedMessage, params object[] args)
method Error (line 83) | public void Error(string formattedMessage, params object[] args)
method Fatal (line 88) | public void Fatal(string formattedMessage, params object[] args)
FILE: src/ServiceWire/LoggerBase.cs
class LoggerBase (line 8) | public abstract class LoggerBase
method FlushLog (line 36) | public virtual void FlushLog()
method GetTimeStamp (line 42) | protected string GetTimeStamp()
method GetTimeStamp (line 49) | protected string GetTimeStamp(DateTime dt)
method WriteBuffer (line 56) | protected void WriteBuffer(int count)
method WriteToFile (line 78) | private void WriteToFile(string[] lines)
method GetFileName (line 98) | private string GetFileName()
method GetCurrentFileOffset (line 136) | private int GetCurrentFileOffset()
method GetSizeFileName (line 142) | private string GetSizeFileName(int offset)
FILE: src/ServiceWire/MemoryDetail.cs
class MemoryDetail (line 5) | public class MemoryDetail
FILE: src/ServiceWire/MessageType.cs
type MessageType (line 3) | public enum MessageType
FILE: src/ServiceWire/MethodSyncInfo.cs
class MethodSyncInfo (line 6) | [Serializable, DataContract]
FILE: src/ServiceWire/NamedPipes/DefaultNamedPipeServerStreamFactory.cs
class DefaultNamedPipeServerStreamFactory (line 5) | public class DefaultNamedPipeServerStreamFactory : INamedPipeServerStrea...
method Create (line 7) | public NamedPipeServerStream Create(string pipeName, PipeDirection dir...
FILE: src/ServiceWire/NamedPipes/INamedPipeServerStreamFactory.cs
type INamedPipeServerStreamFactory (line 5) | public interface INamedPipeServerStreamFactory
method Create (line 7) | NamedPipeServerStream Create(string pipeName, PipeDirection direction,...
FILE: src/ServiceWire/NamedPipes/NpChannel.cs
class NpChannel (line 7) | public class NpChannel : StreamingChannel
method NpChannel (line 18) | public NpChannel(Type serviceType, NpEndPoint npEndPoint, ISerializer ...
FILE: src/ServiceWire/NamedPipes/NpChannelIdentifier.cs
class NpChannelIdentifier (line 5) | internal class NpChannelIdentifier : IChannelIdentifier, IEquatable<NpCh...
method NpChannelIdentifier (line 10) | public NpChannelIdentifier(NpEndPoint npEndPoint)
method Equals (line 16) | public bool Equals(NpChannelIdentifier other)
method Equals (line 22) | public override bool Equals(object obj)
method GetHashCode (line 32) | public override int GetHashCode()
FILE: src/ServiceWire/NamedPipes/NpClient.cs
class NpClient (line 5) | public class NpClient<TInterface> : IDisposable where TInterface : class
method NpClient (line 25) | public NpClient(NpEndPoint npAddress, ISerializer serializer = null, I...
method Dispose (line 38) | public void Dispose()
method Dispose (line 45) | protected virtual void Dispose(bool disposing)
FILE: src/ServiceWire/NamedPipes/NpEndPoint.cs
class NpEndPoint (line 3) | public class NpEndPoint
method NpEndPoint (line 5) | public NpEndPoint(string pipeName, int connectTimeOutMs = 2500)
method NpEndPoint (line 10) | public NpEndPoint(string serverName, string pipeName, int connectTimeO...
FILE: src/ServiceWire/NamedPipes/NpHost.cs
class NpHost (line 6) | public class NpHost : Host
method NpHost (line 38) | public NpHost(string pipeName, ILog log = null, IStats stats = null, I...
method StartListener (line 56) | protected override void StartListener()
method ClientConnectionMade (line 67) | private void ClientConnectionMade(object sender, PipeClientConnectionE...
method Dispose (line 77) | protected override void Dispose(bool disposing)
FILE: src/ServiceWire/NamedPipes/NpListener.cs
class NpListener (line 8) | public class NpListener
method NpListener (line 21) | public NpListener(string pipeName, int maxConnections = 254, ILog log ...
method Start (line 31) | public void Start()
method Stop (line 37) | public void Stop()
method ServerLoop (line 58) | private void ServerLoop()
method ProcessClientThread (line 77) | private void ProcessClientThread(NamedPipeServerStream pipeStream)
method ProcessNextClient (line 98) | public void ProcessNextClient()
FILE: src/ServiceWire/NamedPipes/NpProxy.cs
class NpProxy (line 3) | public class NpProxy
method CreateProxy (line 5) | public static TInterface CreateProxy<TInterface>(NpEndPoint npAddress,...
FILE: src/ServiceWire/NamedPipes/PipeClientConnectionEventArgs.cs
class PipeClientConnectionEventArgs (line 6) | public class PipeClientConnectionEventArgs : EventArgs
method PipeClientConnectionEventArgs (line 8) | public PipeClientConnectionEventArgs(NamedPipeServerStream pipeStream)
FILE: src/ServiceWire/NamedPipes/ReadFileToStream.cs
class ReadFileToStream (line 5) | public class ReadFileToStream
method ReadFileToStream (line 10) | public ReadFileToStream(StreamString str, string filename)
method Start (line 16) | public void Start()
FILE: src/ServiceWire/NamedPipes/StreamString.cs
class StreamString (line 7) | public class StreamString
method StreamString (line 12) | public StreamString(Stream ioStream)
method ReadString (line 18) | public string ReadString()
method WriteString (line 30) | public int WriteString(string outString)
FILE: src/ServiceWire/NetExtensions.cs
class NetExtensions (line 6) | public static class NetExtensions
method ToConfigName (line 11) | public static string ToConfigName(this Type t)
method ToType (line 29) | public static Type ToType(this string configName)
method InheritsFrom (line 49) | public static bool InheritsFrom(this Type t, Type baseType)
method GetDefault (line 60) | public static object GetDefault(this Type t)
method Flatten (line 66) | public static string Flatten(this string src)
FILE: src/ServiceWire/NullLogger.cs
class NullLogger (line 3) | internal class NullLogger : ILog
method Debug (line 5) | public void Debug(string formattedMessage, params object[] args)
method Info (line 9) | public void Info(string formattedMessage, params object[] args)
method Warn (line 13) | public void Warn(string formattedMessage, params object[] args)
method Error (line 17) | public void Error(string formattedMessage, params object[] args)
method Fatal (line 21) | public void Fatal(string formattedMessage, params object[] args)
FILE: src/ServiceWire/NullStats.cs
class NullStats (line 3) | internal class NullStats : IStats
method Log (line 5) | public void Log(string name, float value)
method Log (line 9) | public void Log(string category, string name, float value)
method LogSys (line 13) | public void LogSys()
FILE: src/ServiceWire/ParameterTransferHelper.cs
class ParameterTransferHelper (line 10) | public sealed class ParameterTransferHelper
method ParameterTransferHelper (line 19) | public ParameterTransferHelper(ISerializer serializer, ICompressor com...
method SendParameters (line 25) | public void SendParameters(bool useCompression, int compressionThresho...
method ReceiveParameters (line 262) | public object[] ReceiveParameters(BinaryReader reader)
method GetParameterType (line 465) | private byte GetParameterType(Type type)
method InitializeParamTypes (line 473) | private void InitializeParamTypes()
FILE: src/ServiceWire/ParameterTypes.cs
class ParameterTypes (line 3) | internal sealed class ParameterTypes
FILE: src/ServiceWire/PooledDictionary.cs
class PooledDictionary (line 6) | public sealed class PooledDictionary<TKey, TValue> : IDisposable
method PooledDictionary (line 12) | public PooledDictionary()
method Add (line 19) | public void Add(TKey key, TValue value)
method Count (line 33) | public int Count(TKey key)
method Request (line 44) | public TValue Request(TKey key, Func<TValue> creator = null)
method Release (line 57) | public void Release(TKey key, TValue value)
method Dispose (line 66) | public void Dispose()
FILE: src/ServiceWire/ProxyBuilder.cs
class ProxyBuilder (line 6) | internal sealed class ProxyBuilder
FILE: src/ServiceWire/ProxyFactory.cs
class ProxyFactory (line 9) | public static class ProxyFactory
method CreateProxy (line 19) | public static TInterface CreateProxy<TInterface>(Type channelType, Typ...
method CreateProxy (line 45) | private static TInterface CreateProxy<TInterface>(ProxyBuilder proxyBu...
method CreateProxyBuilder (line 59) | private static ProxyBuilder CreateProxyBuilder(string proxyName, Type ...
method GetAllMethods (line 132) | private static List<MethodInfo> GetAllMethods(List<Type> allInterfaces)
method CreateConstructor (line 140) | private static void CreateConstructor(Type channelType, TypeBuilder ty...
method ConstructMethod (line 157) | private static MethodBuilder ConstructMethod(Type channelType, MethodI...
method GenerateILCodeForMethod (line 171) | private static void GenerateILCodeForMethod(Type channelType, MethodIn...
FILE: src/ServiceWire/SerializationValidator.cs
class SerializationValidator (line 8) | internal static class SerializationValidator
method NonSerializableTypes (line 10) | public static List<string> NonSerializableTypes(this Type type)
method ValidateServiceInterface (line 17) | public static void ValidateServiceInterface(this Type type)
method AnalyzeType (line 49) | private static void AnalyzeType(Type type, List<string> nonSerializabl...
method IsSerializable (line 77) | private static bool IsSerializable(Type type)
FILE: src/ServiceWire/ServiceInstance.cs
class ServiceInstance (line 7) | public class ServiceInstance
FILE: src/ServiceWire/ServiceSyncInfo.cs
class ServiceSyncInfo (line 6) | [Serializable, DataContract]
FILE: src/ServiceWire/ServiceSyncInfoCacheKey.cs
class ServiceSyncInfoCacheKey (line 5) | internal class ServiceSyncInfoCacheKey : IEquatable<ServiceSyncInfoCache...
method ServiceSyncInfoCacheKey (line 10) | public ServiceSyncInfoCacheKey(Type type, IChannelIdentifier channelId...
method Equals (line 16) | public bool Equals(ServiceSyncInfoCacheKey other)
method Equals (line 22) | public override bool Equals(object obj)
method GetHashCode (line 32) | public override int GetHashCode()
FILE: src/ServiceWire/Stats.cs
class Stats (line 11) | public class Stats : LoggerBase, IStats
method Stats (line 17) | public Stats(string statsDirectory = null,
method WriteLines (line 49) | private void WriteLines(string[] lines)
method FlushLog (line 56) | public override void FlushLog()
method WriteBag (line 71) | private void WriteBag(StatsBag bag)
method Log (line 81) | public void Log(string name, float value)
method Log (line 92) | public void Log(string category, string name, float value)
FILE: src/ServiceWire/StatsBag.cs
class StatsBag (line 9) | internal class StatsBag
method StatsBag (line 13) | public StatsBag(bool useUtcTime)
method Clear (line 26) | public void Clear()
method GetTimeStamp (line 32) | protected string GetTimeStamp()
method GetTimeStamp (line 39) | protected string GetTimeStamp(DateTime dt)
method Add (line 46) | public void Add(string category, string name, float value)
method GetDump (line 58) | public string[] GetDump()
class StatInfo (line 89) | internal class StatInfo
method StatInfo (line 106) | public StatInfo(float value)
method Increment (line 111) | public void Increment(float value)
FILE: src/ServiceWire/StreamingChannel.cs
class StreamingChannel (line 12) | public class StreamingChannel : Channel, IDvChannel
method StreamingChannel (line 25) | public StreamingChannel(ISerializer serializer, ICompressor compressor...
method ClearCachedSyncInfo (line 31) | public static void ClearCachedSyncInfo()
method SyncInterface (line 47) | protected override void SyncInterface(Type serviceType,
method InvokeMethod (line 159) | protected override object[] InvokeMethod(string metaData, params objec...
method IsTaskType (line 284) | private static bool IsTaskType(Type type)
method Dispose (line 297) | protected override void Dispose(bool disposing)
FILE: src/ServiceWire/TcpIp/TcpChannel.cs
class TcpChannel (line 9) | public class TcpChannel : StreamingChannel
method TcpChannel (line 16) | public TcpChannel(Type serviceType, IPEndPoint endpoint, ISerializer s...
method TcpChannel (line 26) | public TcpChannel(Type serviceType, TcpEndPoint endpoint, ISerializer ...
method TcpChannel (line 36) | public TcpChannel(Type serviceType, TcpZkEndPoint endpoint, ISerialize...
method CreateSocket (line 50) | private Socket CreateSocket(IPEndPoint endpoint, int connectTimeoutMs)
method Initialize (line 89) | private void Initialize(Type serviceType)
method Dispose (line 110) | protected override void Dispose(bool disposing)
FILE: src/ServiceWire/TcpIp/TcpChannelIdentifier.cs
class TcpChannelIdentifier (line 6) | internal class TcpChannelIdentifier : IChannelIdentifier, IEquatable<Tcp...
method TcpChannelIdentifier (line 10) | public TcpChannelIdentifier(IPEndPoint ipEndpoint)
method Equals (line 15) | public bool Equals(TcpChannelIdentifier other)
method Equals (line 20) | public override bool Equals(object obj)
method GetHashCode (line 29) | public override int GetHashCode()
FILE: src/ServiceWire/TcpIp/TcpClient.cs
class TcpClient (line 6) | public class TcpClient<TInterface> : IDisposable where TInterface : class
method TcpClient (line 10) | public TcpClient(TcpEndPoint endpoint, ISerializer serializer = null, ...
method TcpClient (line 19) | public TcpClient(TcpZkEndPoint endpoint, ISerializer serializer = null...
method TcpClient (line 28) | public TcpClient(IPEndPoint endpoint, ISerializer serializer = null, I...
method InjectLoggerStats (line 37) | [Obsolete]
method Dispose (line 50) | public void Dispose()
method Dispose (line 57) | protected virtual void Dispose(bool disposing)
FILE: src/ServiceWire/TcpIp/TcpEndPoint.cs
class TcpEndPoint (line 5) | public class TcpEndPoint
method TcpEndPoint (line 10) | public TcpEndPoint(IPEndPoint endPoint, int connectTimeOutMs = 2500)
FILE: src/ServiceWire/TcpIp/TcpHost.cs
class TcpHost (line 11) | public class TcpHost : Host
method TcpHost (line 26) | public TcpHost(int port, ILog log = null, IStats stats = null,
method TcpHost (line 50) | public TcpHost(IPEndPoint endpoint, ILog log = null, IStats stats = null,
method StartListener (line 70) | protected override void StartListener()
method Listen (line 86) | private void Listen()
method acceptEventArg_Completed (line 120) | private void acceptEventArg_Completed(object sender, SocketAsyncEventA...
method AcceptNewClient (line 125) | private void AcceptNewClient(SocketAsyncEventArgs e, bool processReque...
method StartProcessingRequestsOnSocket (line 155) | private void StartProcessingRequestsOnSocket(Socket activeSocket)
method Dispose (line 200) | protected override void Dispose(bool disposing)
FILE: src/ServiceWire/TcpIp/TcpProxy.cs
class TcpProxy (line 5) | public static class TcpProxy
method CreateProxy (line 7) | public static TInterface CreateProxy<TInterface>(TcpZkEndPoint endpoin...
method CreateProxy (line 12) | public static TInterface CreateProxy<TInterface>(TcpEndPoint endpoint,...
method CreateProxy (line 17) | public static TInterface CreateProxy<TInterface>(IPEndPoint endpoint, ...
FILE: src/ServiceWire/TcpIp/TcpZkEndPoint.cs
class TcpZkEndPoint (line 5) | public class TcpZkEndPoint
method TcpZkEndPoint (line 12) | public TcpZkEndPoint(string username, string password, IPEndPoint endP...
FILE: src/ServiceWire/ZeroKnowledge/IZkRepository.cs
type IZkRepository (line 8) | public interface IZkRepository
method GetPasswordHashSet (line 10) | ZkPasswordHash GetPasswordHashSet(string username);
class ZkNullRepository (line 13) | public class ZkNullRepository : IZkRepository
method GetPasswordHashSet (line 15) | public ZkPasswordHash GetPasswordHashSet(string username)
FILE: src/ServiceWire/ZeroKnowledge/ZkBigInt.cs
class DigitsArray (line 25) | internal class DigitsArray
method DigitsArray (line 27) | internal DigitsArray(int size)
method DigitsArray (line 32) | internal DigitsArray(int size, int used)
method DigitsArray (line 37) | internal DigitsArray(DType[] copyFrom)
method DigitsArray (line 44) | internal DigitsArray(DigitsArray copyFrom)
method DigitsArray (line 64) | static DigitsArray()
method Allocate (line 73) | public void Allocate(int size)
method Allocate (line 78) | public void Allocate(int size, int used)
method CopyFrom (line 84) | internal void CopyFrom(DType[] source, int sourceOffset, int offset, i...
method CopyTo (line 89) | internal void CopyTo(DType[] array, int offset, int length)
method ResetDataUsed (line 126) | internal void ResetDataUsed()
method ShiftRight (line 150) | internal int ShiftRight(int shiftCount)
method ShiftRight (line 155) | internal static int ShiftRight(DType[] buffer, int shiftCount)
method ShiftLeft (line 193) | internal int ShiftLeft(int shiftCount)
method ShiftLeft (line 198) | internal static int ShiftLeft(DType[] buffer, int shiftCount)
method ShiftLeftWithoutOverflow (line 242) | internal int ShiftLeftWithoutOverflow(int shiftCount)
class BigInteger (line 313) | public class BigInteger
method BigInteger (line 321) | public BigInteger()
method BigInteger (line 330) | public BigInteger(long number)
method BigInteger (line 346) | public BigInteger(ulong number)
method BigInteger (line 362) | public BigInteger(byte[] array)
method BigInteger (line 372) | public BigInteger(byte[] array, int length)
method BigInteger (line 383) | public BigInteger(byte[] array, int offset, int length)
method ConstructFrom (line 388) | private void ConstructFrom(byte[] array, int offset, int length)
method BigInteger (line 437) | public BigInteger(string digits)
method BigInteger (line 450) | public BigInteger(string digits, int radix)
method Construct (line 455) | private void Construct(string digits, int radix)
method BigInteger (line 505) | private BigInteger(DigitsArray digits)
method Add (line 602) | public static BigInteger Add(BigInteger leftSide, BigInteger rightSide)
method Increment (line 622) | public static BigInteger Increment(BigInteger leftSide)
method Subtract (line 655) | public static BigInteger Subtract(BigInteger leftSide, BigInteger righ...
method Decrement (line 675) | public static BigInteger Decrement(BigInteger leftSide)
method Negate (line 726) | public BigInteger Negate()
method Abs (line 736) | public static BigInteger Abs(BigInteger leftSide)
method Multiply (line 808) | public static BigInteger Multiply(BigInteger leftSide, BigInteger righ...
method Divide (line 859) | public static BigInteger Divide(BigInteger leftSide, BigInteger rightS...
method Divide (line 864) | private static void Divide(BigInteger leftSide, BigInteger rightSide, ...
method MultiDivide (line 883) | private static void MultiDivide(BigInteger leftSide, BigInteger rightS...
method SingleDivide (line 964) | private static void SingleDivide(BigInteger leftSide, BigInteger right...
method Modulus (line 1053) | public static BigInteger Modulus(BigInteger leftSide, BigInteger right...
method BitwiseAnd (line 1072) | public static BigInteger BitwiseAnd(BigInteger leftSide, BigInteger ri...
method BitwiseOr (line 1088) | public static BigInteger BitwiseOr(BigInteger leftSide, BigInteger rig...
method Xor (line 1104) | public static BigInteger Xor(BigInteger leftSide, BigInteger rightSide)
method OnesComplement (line 1120) | public static BigInteger OnesComplement(BigInteger leftSide)
method LeftShift (line 1141) | public static BigInteger LeftShift(BigInteger leftSide, int shiftCount)
method RightShift (line 1179) | public static BigInteger RightShift(BigInteger leftSide, int shiftCount)
method CompareTo (line 1220) | public int CompareTo(BigInteger value)
method Compare (line 1254) | public static int Compare(BigInteger leftSide, BigInteger rightSide)
method Equals (line 1383) | public override bool Equals(object obj)
method GetHashCode (line 1416) | public override int GetHashCode()
method ToString (line 1426) | public override string ToString()
method ToString (line 1438) | public string ToString(int radix)
method ToHexString (line 1484) | public string ToHexString()
method ToInt16 (line 1504) | public static int ToInt16(BigInteger value)
method ToUInt16 (line 1519) | public static uint ToUInt16(BigInteger value)
method ToInt32 (line 1534) | public static int ToInt32(BigInteger value)
method ToUInt32 (line 1549) | public static uint ToUInt32(BigInteger value)
method ToInt64 (line 1564) | public static long ToInt64(BigInteger value)
method ToUInt64 (line 1579) | public static ulong ToUInt64(BigInteger value)
method ToByteArray (line 1588) | public static byte[] ToByteArray(BigInteger value)
FILE: src/ServiceWire/ZeroKnowledge/ZkCrypto.cs
class ZkCrypto (line 9) | public class ZkCrypto
method ZkCrypto (line 15) | public ZkCrypto(byte[] key, byte[] iv)
method Encrypt (line 24) | public byte[] Encrypt(byte[] data)
method Decrypt (line 39) | public byte[] Decrypt(byte[] encrypted)
FILE: src/ServiceWire/ZeroKnowledge/ZkExt.cs
class ZkExt (line 5) | public static class ZkExt
method ConvertToBytes (line 7) | public static byte[] ConvertToBytes(this string val)
method ConverToString (line 12) | public static string ConverToString(this byte[] bytes)
method IsEqualTo (line 17) | public static bool IsEqualTo(this byte[] a1, byte[] a2)
FILE: src/ServiceWire/ZeroKnowledge/ZkPasswordHash.cs
class ZkPasswordHash (line 3) | public class ZkPasswordHash
FILE: src/ServiceWire/ZeroKnowledge/ZkProtocol.cs
class ZkProtocol (line 10) | public class ZkProtocol
method ZkProtocol (line 16) | public ZkProtocol()
method HashCredentials (line 29) | public ZkPasswordHash HashCredentials(string username, string password)
method GetClientEphemeralA (line 48) | public byte[] GetClientEphemeralA(byte[] aRand)
method GetServerEphemeralB (line 61) | public byte[] GetServerEphemeralB(byte[] salt, byte[] verifier, byte[]...
method CalculateRandomScramble (line 73) | public byte[] CalculateRandomScramble(byte[] ephemeralA, byte[] epheme...
method ClientComputeSessionKey (line 88) | public byte[] ClientComputeSessionKey(byte[] salt, string username, st...
method ServerComputeSessionKey (line 104) | public byte[] ServerComputeSessionKey(byte[] salt, byte[] key, byte[] ...
method ClientCreateSessionHash (line 119) | public byte[] ClientCreateSessionHash(string username, byte[] salt, by...
method ServerCreateSessionHash (line 132) | public byte[] ServerCreateSessionHash(byte[] aEphemeral, byte[] client...
method CryptRand (line 143) | public byte[] CryptRand(int bits = 4096)
method ComputeHash (line 156) | public byte[] ComputeHash(params byte[][] items)
method Combine (line 162) | public byte[] Combine(params byte[][] arrays)
FILE: src/ServiceWire/ZeroKnowledge/ZkSafePrimes.cs
class ZkSafePrimes (line 3) | public static class ZkSafePrimes
method GetSafePrime (line 31) | public static int GetSafePrime(int index)
FILE: src/ServiceWire/ZeroKnowledge/ZkSession.cs
class ZkSession (line 7) | public class ZkSession
method ZkSession (line 26) | public ZkSession(IZkRepository respository, ILog logger, IStats stats)
method ProcessZkProof (line 35) | public bool ProcessZkProof(BinaryReader binReader, BinaryWriter binWri...
method ProcessZkInitiation (line 56) | public bool ProcessZkInitiation(BinaryReader binReader, BinaryWriter b...
FILE: src/ServiceWireTestHostPlusClient/Program.cs
class Program (line 7) | public class Program
method Main (line 9) | public static void Main()
type ISimpleError (line 35) | public interface ISimpleError
method TestReturn3 (line 37) | int TestReturn3();
method RaiseAnError (line 38) | void RaiseAnError();
class SimpleError (line 41) | public class SimpleError : ISimpleError
method TestReturn3 (line 43) | public int TestReturn3() => 3;
method RaiseAnError (line 44) | public void RaiseAnError()
FILE: src/Tests/Integration/ServiceWireTestClient1/Program.cs
class Program (line 17) | class Program
method Main (line 19) | private static void Main(string[] args)
method RunTest (line 31) | private static void RunTest(IPEndPoint ipEndpoint, string ip)
FILE: src/Tests/Integration/ServiceWireTestClient2/Program.cs
class Program (line 14) | class Program
method Main (line 16) | private static void Main(string[] args)
method RunTest (line 28) | private static async Task RunTest(IPEndPoint ipEndpoint, string ip)
FILE: src/Tests/Integration/ServiceWireTestHost/Program.cs
class Program (line 14) | class Program
method Main (line 16) | static void Main(string[] args)
class ValTypes (line 60) | public class ValTypes : IValTypes
method GetDecimal (line 62) | public decimal GetDecimal(decimal input)
method GetDecimalAsync (line 67) | public Task<decimal> GetDecimalAsync(decimal input)
method OutDecimal (line 72) | public bool OutDecimal(decimal val)
method OutDecimalAsync (line 78) | public Task<bool> OutDecimalAsync(decimal val)
class NetTester (line 84) | public class NetTester : INetTester
method GetId (line 86) | public Guid GetId(string source, double weight, int quantity, DateTime...
method Get (line 91) | public TestResponse Get(Guid id, string label, double weight, out long...
method GetItems (line 97) | public List<string> GetItems(Guid id)
method GetItemsAsync (line 106) | public Task<List<string>> GetItemsAsync(Guid id)
method TestLong (line 111) | public long TestLong(out long id1, out long id2)
method TestEnum (line 118) | public eResult TestEnum(out eResult e1, ref eResult e2)
class MyTester (line 126) | public class MyTester : IMyTester
method MyTester (line 132) | public MyTester()
method GetId (line 143) | public Guid GetId(string source, double weight, int quantity)
method Get (line 148) | public TestResponse Get(Guid id, string label, double weight, out int ...
method GetItems (line 154) | public List<string> GetItems(Guid id, int[] vals)
FILE: src/Tests/ServiceWireTestCommon/TestContracts.cs
type eResult (line 10) | public enum eResult : UInt16
type IValTypes (line 16) | public interface IValTypes
method GetDecimal (line 18) | decimal GetDecimal(decimal input);
method GetDecimalAsync (line 19) | Task<decimal> GetDecimalAsync(decimal input);
method OutDecimal (line 20) | bool OutDecimal(decimal val);
method OutDecimalAsync (line 21) | Task<bool> OutDecimalAsync(decimal val);
type INetTester (line 24) | public interface INetTester
method GetId (line 26) | Guid GetId(string source, double weight, int quantity, DateTime dt);
method Get (line 27) | TestResponse Get(Guid id, string label, double weight, out long quanti...
method TestLong (line 28) | long TestLong(out long id1, out long id2);
method TestEnum (line 29) | eResult TestEnum(out eResult e1, ref eResult e2);
method GetItems (line 30) | List<string> GetItems(Guid id);
method GetItemsAsync (line 31) | Task<List<string>> GetItemsAsync(Guid id);
type IMyTester (line 34) | public interface IMyTester
method GetId (line 36) | Guid GetId(string source, double weight, int quantity);
method Get (line 37) | TestResponse Get(Guid id, string label, double weight, out int quantity);
method GetItems (line 38) | List<string> GetItems(Guid id, int[] vals);
type TestResponse (line 41) | [Serializable]
class NetTcpTesterProxy (line 50) | public class NetTcpTesterProxy : TcpClient<INetTester>, INetTester
method NetTcpTesterProxy (line 52) | public NetTcpTesterProxy(TcpEndPoint endpoint) : base(endpoint)
method NetTcpTesterProxy (line 56) | public NetTcpTesterProxy(IPEndPoint endpoint) : base(endpoint)
method GetId (line 60) | public Guid GetId(string source, double weight, int quantity, DateTime...
method Get (line 65) | public TestResponse Get(Guid id, string label, double weight, out long...
method GetItems (line 70) | public List<string> GetItems(Guid id)
method GetItemsAsync (line 75) | public Task<List<string>> GetItemsAsync(Guid id)
method TestLong (line 80) | public long TestLong(out long id1, out long id2)
method TestEnum (line 87) | public eResult TestEnum(out eResult e1, ref eResult e2)
class NetNpTesterProxy (line 95) | public class NetNpTesterProxy : NpClient<INetTester>, INetTester
method NetNpTesterProxy (line 97) | public NetNpTesterProxy(NpEndPoint npAddress) : base(npAddress)
method GetId (line 101) | public Guid GetId(string source, double weight, int quantity, DateTime...
method Get (line 106) | public TestResponse Get(Guid id, string label, double weight, out long...
method GetItems (line 111) | public List<string> GetItems(Guid id)
method GetItemsAsync (line 116) | public Task<List<string>> GetItemsAsync(Guid id)
method TestLong (line 121) | public long TestLong(out long id1, out long id2)
method TestEnum (line 126) | public eResult TestEnum(out eResult e1, ref eResult e2)
class NetTcpMyTesterProxy (line 132) | public class NetTcpMyTesterProxy : TcpClient<IMyTester>, IMyTester
method NetTcpMyTesterProxy (line 134) | public NetTcpMyTesterProxy(IPEndPoint endpoint)
method GetId (line 139) | public Guid GetId(string source, double weight, int quantity)
method Get (line 144) | public TestResponse Get(Guid id, string label, double weight, out int ...
method GetItems (line 149) | public List<string> GetItems(Guid id, int[] vals)
class NetNpMyTesterProxy (line 155) | public class NetNpMyTesterProxy : NpClient<IMyTester>, IMyTester
method NetNpMyTesterProxy (line 157) | public NetNpMyTesterProxy(NpEndPoint npAddress)
method GetId (line 162) | public Guid GetId(string source, double weight, int quantity)
method Get (line 167) | public TestResponse Get(Guid id, string label, double weight, out int ...
method GetItems (line 172) | public List<string> GetItems(Guid id, int[] vals)
FILE: src/Tests/Unit/ServiceWireTests/AsyncTests.cs
class AsyncTests (line 14) | public class AsyncTests : IDisposable
method Divide_ShouldThrow_Exception (line 18) | [Fact]
method StartPipeListener (line 35) | void StartPipeListener()
method Dispose (line 43) | public void Dispose()
type ISum (line 49) | public interface ISum
method Divide (line 51) | Task<double> Divide(double a, int b);
class Sum (line 54) | public class Sum : ISum
method Divide (line 56) | public Task<double> Divide(double a, int b)
class PipeException (line 65) | internal class PipeException : ApplicationException
method PipeException (line 67) | public PipeException(string message = null)
class CustomPipeSerializer (line 73) | internal class CustomPipeSerializer : ISerializer
method CustomPipeSerializer (line 77) | public CustomPipeSerializer()
method Serialize (line 85) | public byte[] Serialize<T>(T obj) => obj == null ? null : JsonSerializ...
method Serialize (line 87) | public byte[] Serialize(object obj, string typeConfigName) =>
method Deserialize (line 90) | public T Deserialize<T>(byte[] bytes) => bytes == null || bytes.Length...
method Deserialize (line 94) | public object Deserialize(byte[] bytes, string typeConfigName)
class PipeExceptionJsonConverter (line 103) | internal class PipeExceptionJsonConverter : JsonConverter<PipeException>
method Read (line 105) | public override PipeException Read(ref Utf8JsonReader reader, Type typ...
method Write (line 139) | public override void Write(Utf8JsonWriter writer, PipeException value,...
FILE: src/Tests/Unit/ServiceWireTests/INetTester.cs
type INetTester (line 8) | public interface INetTester
method Min (line 10) | int Min(int a, int b);
method Range (line 11) | Dictionary<int, int> Range(int start, int count);
method Get (line 12) | TestResponse Get(Guid id, string label, double weight, out int quantity);
method CalculateAsync (line 13) | Task<int> CalculateAsync(int a, int b);
method GetStrings (line 14) | string[] GetStrings();
type TestResponse (line 17) | [Serializable]
class NetTester (line 26) | public class NetTester : INetTester
method Min (line 28) | public int Min(int a, int b)
method Range (line 33) | public Dictionary<int, int> Range(int start, int count)
method CalculateAsync (line 38) | public Task<int> CalculateAsync(int a, int b)
method Get (line 43) | public TestResponse Get(Guid id, string label, double weight, out int ...
method GetStrings (line 49) | public string[] GetStrings()
FILE: src/Tests/Unit/ServiceWireTests/InterceptionTests.cs
class InterceptionTests (line 8) | public class InterceptionTests
method SimpleTest (line 10) | [Fact]
method SimpleTimingTest (line 41) | [Fact]
method SimpleErrorTestNoThrow (line 113) | [Fact]
method SimpleErrorTestThrowOriginalError (line 140) | [Fact]
type ISimpleMath (line 176) | public interface ISimpleMath
method Add (line 178) | int Add(int a, int b);
method Divide (line 179) | int Divide(int a, int b);
class SimpleMath (line 182) | public class SimpleMath : ISimpleMath
method Add (line 184) | public int Add(int a, int b)
method Divide (line 189) | public int Divide(int a, int b)
type ISimpleMath2 (line 195) | public interface ISimpleMath2
method Add (line 197) | int Add(int a, int b);
method Divide (line 198) | int Divide(int a, int b);
class SimpleMath2 (line 201) | public class SimpleMath2 : ISimpleMath2
method Add (line 203) | public int Add(int a, int b)
method Divide (line 208) | public int Divide(int a, int b)
type ISimpleError (line 214) | public interface ISimpleError
method RaiseAnError (line 216) | void RaiseAnError();
class SimpleError (line 219) | public class SimpleError : ISimpleError
method RaiseAnError (line 221) | public void RaiseAnError()
FILE: src/Tests/Unit/ServiceWireTests/NewtonsoftSerializer.cs
class NewtonsoftSerializer (line 12) | public class NewtonsoftSerializer : ISerializer
method Deserialize (line 19) | public T Deserialize<T>(byte[] bytes)
method Deserialize (line 26) | public object Deserialize(byte[] bytes, string typeConfigName)
method Serialize (line 35) | public byte[] Serialize<T>(T obj)
method Serialize (line 42) | public byte[] Serialize(object obj, string typeConfigName)
FILE: src/Tests/Unit/ServiceWireTests/NpTests.cs
class NpTests (line 10) | public class NpTests : IDisposable
method CreateEndPoint (line 19) | private NpEndPoint CreateEndPoint()
method NpTests (line 24) | public NpTests()
method SimpleTest (line 38) | [Fact]
method SimpleNewtonsoftSerializerTest (line 50) | [Fact]
method SimpleProtobufSerializerTest (line 68) | [Fact]
method CalculateAsyncTest (line 86) | [Fact]
method SimpleParallelTest (line 98) | [Fact(Skip = "Avoid Parallel.For")]
method ResponseTest (line 118) | [Fact]
method ResponseParallelTest (line 134) | [Fact(Skip = "Avoid Parallel.For")]
method ResponseWithOutParameterTest (line 165) | [Fact]
method ResponseWithOutParameterNewtonsoftSerializerTest (line 175) | [Fact]
method GetStringsTest (line 194) | [Fact]
method Dispose (line 202) | public void Dispose()
FILE: src/Tests/Unit/ServiceWireTests/ParameterTransferHelperTests.cs
class ParameterTransferHelperTests (line 8) | public class ParameterTransferHelperTests
method SimpleTypesTest (line 10) | [Fact]
method SimpleTypesMultipleTest (line 47) | [Fact]
method ArrayOfSimpleTypesTest (line 73) | [Fact]
method TestArraySimpleType (line 125) | private void TestArraySimpleType(object obj)
method TestMultiple (line 134) | private void TestMultiple(params object[] obj)
method TestSingle (line 145) | private void TestSingle(object obj)
method RunInAndOut (line 153) | private object[] RunInAndOut(params object[] obj)
FILE: src/Tests/Unit/ServiceWireTests/ProtobufSerializer.cs
class ProtobufSerializer (line 13) | public class ProtobufSerializer : ISerializer
method Deserialize (line 15) | public T Deserialize<T>(byte[] bytes)
method Deserialize (line 24) | public object Deserialize(byte[] bytes, string typeConfigName)
method Serialize (line 35) | public byte[] Serialize<T>(T obj)
method Serialize (line 54) | public byte[] Serialize(object obj, string typeConfigName)
FILE: src/Tests/Unit/ServiceWireTests/SequentialCollection.cs
class SequentialCollectionTcp (line 10) | [CollectionDefinition("Sequential Collection Tcp", DisableParallelizatio...
class SequentialCollectionTcpZk (line 15) | [CollectionDefinition("Sequential Collection TcpZk", DisableParallelizat...
FILE: src/Tests/Unit/ServiceWireTests/TcpTests.cs
class TcpTests (line 9) | [Collection("Sequential Collection Tcp")]
method CreateEndPoint (line 18) | private IPEndPoint CreateEndPoint()
method TcpTests (line 23) | public TcpTests()
method SimpleTest (line 36) | [Fact]
method CalculateAsyncTest (line 50) | [Fact]
method SimpleParallelTest (line 64) | [Fact(Skip = "Avoid Parallel.For")]
method ResponseTest (line 89) | [Fact]
method ResponseParallelTest (line 107) | [Fact(Skip = "Avoid Parallel.For")]
method ResponseWithOutParameterTest (line 139) | [Fact]
method GetStringsTest (line 151) | [Fact]
method Dispose (line 162) | public void Dispose()
FILE: src/Tests/Unit/ServiceWireTests/TcpZkTests.cs
class FakeZkRepository (line 10) | public class FakeZkRepository : IZkRepository
method GetPasswordHashSet (line 16) | public ZkPasswordHash GetPasswordHashSet(string username)
class TcpZkTests (line 23) | [Collection("Sequential Collection TcpZk")]
method CreateEndPoint (line 37) | private IPEndPoint CreateEndPoint()
method CreateZkClientEndPoint (line 42) | private TcpZkEndPoint CreateZkClientEndPoint()
method TcpZkTests (line 47) | public TcpZkTests()
method SimpleZkTest (line 59) | [Fact]
method CalculateAsyncTest (line 73) | [Fact]
method SimpleParallelZkTest (line 87) | [Fact(Skip = "Avoid Parallel.For")]
method ResponseZkTest (line 111) | [Fact]
method ResponseParallelTest (line 135) | [Fact(Skip = "Avoid Parallel.For")]
method Dispose (line 169) | public void Dispose()
FILE: src/Tests/Unit/ServiceWireTests/ZkProtocolTests.cs
class ZkProtocolTests (line 6) | public class ZkProtocolTests
method BigIntegerArrayTest (line 8) | [Fact]
method SimpleProtocolTest (line 22) | [Fact]
Condensed preview — 117 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (419K chars).
[
{
"path": ".gitattributes",
"chars": 483,
"preview": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Custom for Visual Studio\n*.cs diff=csharp\n*.sln"
},
{
"path": ".github/workflows/build-and-test.yml",
"chars": 993,
"preview": "name: .NET Build and Tests in Linux and Windows\n\non:\n push:\n branches: [ \"master\" ]\n pull_request:\n branches: [ "
},
{
"path": ".gitignore",
"chars": 2161,
"preview": "#################\n## Eclipse\n#################\n\n*.pydevproject\n.project\n.metadata\nbin/\ntmp/\n*.tmp\n*.bak\n*.swp\n*~.nib\nloc"
},
{
"path": "README.md",
"chars": 17391,
"preview": "[](https://github.com/"
},
{
"path": "src/Benchmarks/ServiceWire.Benchmarks/ConnectionBenchmarks.cs",
"chars": 2150,
"preview": "using System;\nusing ServiceWire.NamedPipes;\nusing BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing Service"
},
{
"path": "src/Benchmarks/ServiceWire.Benchmarks/INetTester.cs",
"chars": 1353,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace ServiceWire"
},
{
"path": "src/Benchmarks/ServiceWire.Benchmarks/NamedPipesBenchmarks.cs",
"chars": 3093,
"preview": "using System;\nusing ServiceWire.NamedPipes;\nusing BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\n\nnamespace Se"
},
{
"path": "src/Benchmarks/ServiceWire.Benchmarks/NewtonSoftSerializer.cs",
"chars": 1589,
"preview": "using System;\nusing System.Text;\nusing Newtonsoft.Json;\n\nnamespace ServiceWire.Benchmarks\n{\n public class Newtonsoft"
},
{
"path": "src/Benchmarks/ServiceWire.Benchmarks/Program.cs",
"chars": 2285,
"preview": "using System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing BenchmarkDotNet.Running;\n\nnamespace"
},
{
"path": "src/Benchmarks/ServiceWire.Benchmarks/ServiceWire.Benchmarks.csproj",
"chars": 829,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFrameworks>net8.0;net6.0;net48</TargetFrameworks>\n\t</Prope"
},
{
"path": "src/Benchmarks/ServiceWire.Benchmarks/TcpBenchmarks.cs",
"chars": 3122,
"preview": "using System;\nusing ServiceWire.TcpIp;\nusing BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Jobs;\nusing System.Net;\n"
},
{
"path": "src/Demo/DemoClient/App.config",
"chars": 180,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n <startup> \n <supportedRuntime version=\"v4.0\" sku=\".NET"
},
{
"path": "src/Demo/DemoClient/DemoClient.csproj",
"chars": 1157,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup Condition=\" '$(OS)' != 'Windows_NT' \">\n\t\t<TargetFrameworks>net6.0;ne"
},
{
"path": "src/Demo/DemoClient/Program.cs",
"chars": 3620,
"preview": "using DemoCommon;\nusing ServiceWire;\nusing ServiceWire.TcpIp;\nusing System;\nusing System.Collections.Generic;\nusing Sys"
},
{
"path": "src/Demo/DemoCommon/Contracts.cs",
"chars": 866,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace DemoCommon\n{\n\tpublic interface"
},
{
"path": "src/Demo/DemoCommon/DemoCommon.csproj",
"chars": 306,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup Condition=\" '$(OS)' != 'Windows_NT' \">\n\t\t<TargetFrameworks>net6.0;ne"
},
{
"path": "src/Demo/DemoHost/App.config",
"chars": 180,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n <startup> \n <supportedRuntime version=\"v4.0\" sku=\".NET"
},
{
"path": "src/Demo/DemoHost/DemoHost.csproj",
"chars": 1157,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup Condition=\" '$(OS)' != 'Windows_NT' \">\n\t\t<TargetFrameworks>net6.0;ne"
},
{
"path": "src/Demo/DemoHost/Program.cs",
"chars": 3802,
"preview": "using DemoCommon;\nusing ServiceWire;\nusing ServiceWire.TcpIp;\nusing ServiceWire.ZeroKnowledge;\nusing System;\nusing Syst"
},
{
"path": "src/License.txt",
"chars": 5873,
"preview": "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n COPYRIGHT NOTICES AND"
},
{
"path": "src/Serializers/ServiceWire.Serializers/BinaryFormatterSerializer.cs",
"chars": 1771,
"preview": "using System;\nusing System.IO;\nusing System.Runtime.Serialization;\nusing System.Runtime.Serialization.Formatters.Binary"
},
{
"path": "src/Serializers/ServiceWire.Serializers/ServiceWire.Serializers.csproj",
"chars": 299,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netstandard2.0</TargetFramework>\n </PropertyG"
},
{
"path": "src/ServiceWire/Aspects/CrossCuttingConcerns.cs",
"chars": 783,
"preview": "using System;\n\nnamespace ServiceWire.Aspects\n{\n public class CrossCuttingConcerns\n {\n /// <summary>\n "
},
{
"path": "src/ServiceWire/Aspects/InterceptChannel.cs",
"chars": 9470,
"preview": "using System;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.Reflection;\n\nnamespac"
},
{
"path": "src/ServiceWire/Aspects/InterceptPoint.cs",
"chars": 211,
"preview": "namespace ServiceWire.Aspects\n{\n public class InterceptPoint\n {\n public int Id { get; set; }\n publi"
},
{
"path": "src/ServiceWire/Aspects/Interceptor.cs",
"chars": 1517,
"preview": "using System;\n\nnamespace ServiceWire.Aspects\n{\n public static class Interceptor\n {\n public static TTarget "
},
{
"path": "src/ServiceWire/Channel.cs",
"chars": 2147,
"preview": "using System;\n\nnamespace ServiceWire\n{\n public abstract class Channel : IDisposable\n {\n protected Type _ser"
},
{
"path": "src/ServiceWire/DefaultCompressor.cs",
"chars": 1102,
"preview": "using System.IO;\nusing System.IO.Compression;\n\nnamespace ServiceWire\n{\n public class DefaultCompressor : ICompressor"
},
{
"path": "src/ServiceWire/DefaultSerializer.cs",
"chars": 1143,
"preview": "using System;\nusing System.IO;\nusing System.Text.Json;\n\nnamespace ServiceWire\n{\n public class DefaultSerializer : IS"
},
{
"path": "src/ServiceWire/DefaultTypeMaker.cs",
"chars": 348,
"preview": "using System;\n\nnamespace ServiceWire\n{\n internal class DefaultTypeMaker\n {\n public object GetDefault(Type "
},
{
"path": "src/ServiceWire/Host.cs",
"chars": 21350,
"preview": "using ServiceWire.ZeroKnowledge;\nusing System;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nus"
},
{
"path": "src/ServiceWire/IChannelIdentifier.cs",
"chars": 79,
"preview": "namespace ServiceWire\n{\n public interface IChannelIdentifier\n {\n }\n}\n"
},
{
"path": "src/ServiceWire/ICompressor.cs",
"chars": 160,
"preview": "namespace ServiceWire\n{\n public interface ICompressor\n {\n byte[] Compress(byte[] data);\n byte[] DeC"
},
{
"path": "src/ServiceWire/IDvChannel.cs",
"chars": 306,
"preview": "namespace ServiceWire\n{\n /// <summary>\n /// The channel behavior exposed on the client level.\n /// </summary>\n "
},
{
"path": "src/ServiceWire/ILog.cs",
"chars": 398,
"preview": "namespace ServiceWire\n{\n public interface ILog\n {\n void Debug(string formattedMessage, params object[] arg"
},
{
"path": "src/ServiceWire/ISerializer.cs",
"chars": 273,
"preview": "namespace ServiceWire\n{\n public interface ISerializer\n {\n byte[] Serialize<T>(T obj);\n byte[] Seria"
},
{
"path": "src/ServiceWire/IStats.cs",
"chars": 171,
"preview": "namespace ServiceWire\n{\n public interface IStats\n {\n void Log(string name, float value);\n void Log("
},
{
"path": "src/ServiceWire/LogLevel.cs",
"chars": 173,
"preview": "namespace ServiceWire\n{\n public enum LogLevel\n {\n None = 0,\n Fatal = 1,\n Error = 2,\n "
},
{
"path": "src/ServiceWire/LogOptions.cs",
"chars": 132,
"preview": "namespace ServiceWire\n{\n public enum LogOptions\n {\n LogOnlyToFile,\n LogOnlyToConsole,\n LogTo"
},
{
"path": "src/ServiceWire/LogRollOptions.cs",
"chars": 113,
"preview": "namespace ServiceWire\n{\n public enum LogRollOptions\n {\n Daily,\n Hourly,\n Size\n }\n}"
},
{
"path": "src/ServiceWire/Logger.cs",
"chars": 3590,
"preview": "using System.IO;\nusing System.Reflection;\nusing System.Threading.Tasks;\n\nnamespace ServiceWire\n{\n public class Logge"
},
{
"path": "src/ServiceWire/LoggerBase.cs",
"chars": 5254,
"preview": "using System;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace Servic"
},
{
"path": "src/ServiceWire/MemoryDetail.cs",
"chars": 306,
"preview": "using System;\n\nnamespace ServiceWire\n{\n public class MemoryDetail\n {\n public ulong TotalVisibleMemorySize "
},
{
"path": "src/ServiceWire/MessageType.cs",
"chars": 285,
"preview": "namespace ServiceWire\n{\n public enum MessageType\n {\n TerminateConnection = 0,\n MethodInvocation = 1,"
},
{
"path": "src/ServiceWire/MethodSyncInfo.cs",
"chars": 481,
"preview": "using System;\nusing System.Runtime.Serialization;\n\nnamespace ServiceWire\n{\n [Serializable, DataContract]\n public "
},
{
"path": "src/ServiceWire/NamedPipes/DefaultNamedPipeServerStreamFactory.cs",
"chars": 558,
"preview": "using System.IO.Pipes;\n\nnamespace ServiceWire.NamedPipes\n{\n public class DefaultNamedPipeServerStreamFactory : IName"
},
{
"path": "src/ServiceWire/NamedPipes/INamedPipeServerStreamFactory.cs",
"chars": 347,
"preview": "using System.IO.Pipes;\n\nnamespace ServiceWire.NamedPipes\n{\n public interface INamedPipeServerStreamFactory\n {\n "
},
{
"path": "src/ServiceWire/NamedPipes/NpChannel.cs",
"chars": 1778,
"preview": "using System;\nusing System.IO;\nusing System.IO.Pipes;\n\nnamespace ServiceWire.NamedPipes\n{\n public class NpChannel : S"
},
{
"path": "src/ServiceWire/NamedPipes/NpChannelIdentifier.cs",
"chars": 1008,
"preview": "using System;\n\nnamespace ServiceWire.NamedPipes\n{\n internal class NpChannelIdentifier : IChannelIdentifier, IEquatab"
},
{
"path": "src/ServiceWire/NamedPipes/NpClient.cs",
"chars": 1974,
"preview": "using System;\n\nnamespace ServiceWire.NamedPipes\n{\n public class NpClient<TInterface> : IDisposable where TInterface :"
},
{
"path": "src/ServiceWire/NamedPipes/NpEndPoint.cs",
"chars": 634,
"preview": "namespace ServiceWire.NamedPipes\n{\n public class NpEndPoint\n {\n public NpEndPoint(string pipeName, int conn"
},
{
"path": "src/ServiceWire/NamedPipes/NpHost.cs",
"chars": 3322,
"preview": "using System;\nusing System.IO;\n\nnamespace ServiceWire.NamedPipes\n{\n public class NpHost : Host\n {\n private "
},
{
"path": "src/ServiceWire/NamedPipes/NpListener.cs",
"chars": 3969,
"preview": "using System;\nusing System.IO.Pipes;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace ServiceWire.Named"
},
{
"path": "src/ServiceWire/NamedPipes/NpProxy.cs",
"chars": 419,
"preview": "namespace ServiceWire.NamedPipes\n{\n public class NpProxy\n {\n public static TInterface CreateProxy<TInterfac"
},
{
"path": "src/ServiceWire/NamedPipes/PipeClientConnectionEventArgs.cs",
"chars": 357,
"preview": "using System;\nusing System.IO.Pipes;\n\nnamespace ServiceWire.NamedPipes\n{\n public class PipeClientConnectionEventArgs"
},
{
"path": "src/ServiceWire/NamedPipes/ReadFileToStream.cs",
"chars": 469,
"preview": "using System.IO;\n\nnamespace ServiceWire.NamedPipes\n{\n public class ReadFileToStream\n {\n private readonly s"
},
{
"path": "src/ServiceWire/NamedPipes/StreamString.cs",
"chars": 1220,
"preview": "using System;\nusing System.IO;\nusing System.Text;\n\nnamespace ServiceWire.NamedPipes\n{\n public class StreamString\n "
},
{
"path": "src/ServiceWire/NetExtensions.cs",
"chars": 2576,
"preview": "using System;\nusing System.Text.RegularExpressions;\n\nnamespace ServiceWire\n{\n public static class NetExtensions\n "
},
{
"path": "src/ServiceWire/NullLogger.cs",
"chars": 542,
"preview": "namespace ServiceWire\n{\n internal class NullLogger : ILog\n {\n public void Debug(string formattedMessage, p"
},
{
"path": "src/ServiceWire/NullStats.cs",
"chars": 284,
"preview": "namespace ServiceWire\n{\n internal class NullStats : IStats\n {\n public void Log(string name, float value)\n "
},
{
"path": "src/ServiceWire/ParameterTransferHelper.cs",
"chars": 26783,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing Sy"
},
{
"path": "src/ServiceWire/ParameterTypes.cs",
"chars": 2123,
"preview": "namespace ServiceWire\n{\n internal sealed class ParameterTypes\n {\n internal const byte Unknown = 0x00;\n "
},
{
"path": "src/ServiceWire/PooledDictionary.cs",
"chars": 2714,
"preview": "using System;\nusing System.Collections.Concurrent;\n\nnamespace ServiceWire\n{\n public sealed class PooledDictionary<TK"
},
{
"path": "src/ServiceWire/ProxyBuilder.cs",
"chars": 429,
"preview": "using System;\nusing System.Reflection.Emit;\n\nnamespace ServiceWire\n{\n internal sealed class ProxyBuilder\n {\n "
},
{
"path": "src/ServiceWire/ProxyFactory.cs",
"chars": 15852,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing System.Reflection.Emit;\nusing System.Thre"
},
{
"path": "src/ServiceWire/SerializationValidator.cs",
"chars": 3421,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Reflection;\nusing System.Runtime.Serialization;\n\nnamespace"
},
{
"path": "src/ServiceWire/ServiceInstance.cs",
"chars": 521,
"preview": "using System;\nusing System.Collections.Concurrent;\nusing System.Reflection;\n\nnamespace ServiceWire\n{\n public class Se"
},
{
"path": "src/ServiceWire/ServiceSyncInfo.cs",
"chars": 493,
"preview": "using System;\nusing System.Runtime.Serialization;\n\nnamespace ServiceWire\n{\n [Serializable, DataContract]\n public "
},
{
"path": "src/ServiceWire/ServiceSyncInfoCacheKey.cs",
"chars": 1013,
"preview": "using System;\n\nnamespace ServiceWire\n{\n internal class ServiceSyncInfoCacheKey : IEquatable<ServiceSyncInfoCacheKey>"
},
{
"path": "src/ServiceWire/ServiceWire.csproj",
"chars": 1958,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFrameworks>netstandard2.0</TargetFrameworks>\n\t</PropertyGr"
},
{
"path": "src/ServiceWire/Stats.cs",
"chars": 3713,
"preview": "using System;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Refl"
},
{
"path": "src/ServiceWire/StatsBag.cs",
"chars": 3549,
"preview": "using System;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Th"
},
{
"path": "src/ServiceWire/StreamingChannel.cs",
"chars": 14487,
"preview": "using ServiceWire.ZeroKnowledge;\nusing System;\nusing System.Collections.Concurrent;\nusing System.Diagnostics;\nusing Syst"
},
{
"path": "src/ServiceWire/TcpIp/TcpChannel.cs",
"chars": 4324,
"preview": "using System;\nusing System.IO;\nusing System.Net;\nusing System.Net.Sockets;\nusing System.Threading;\n\nnamespace ServiceWir"
},
{
"path": "src/ServiceWire/TcpIp/TcpChannelIdentifier.cs",
"chars": 833,
"preview": "using System;\nusing System.Net;\n\nnamespace ServiceWire.TcpIp\n{\n internal class TcpChannelIdentifier : IChannelIdenti"
},
{
"path": "src/ServiceWire/TcpIp/TcpClient.cs",
"chars": 2712,
"preview": "using System;\nusing System.Net;\n\nnamespace ServiceWire.TcpIp\n{\n public class TcpClient<TInterface> : IDisposable wher"
},
{
"path": "src/ServiceWire/TcpIp/TcpEndPoint.cs",
"chars": 398,
"preview": "using System.Net;\n\nnamespace ServiceWire.TcpIp\n{\n public class TcpEndPoint\n {\n public IPEndPoint EndPoint "
},
{
"path": "src/ServiceWire/TcpIp/TcpHost.cs",
"chars": 8409,
"preview": "using ServiceWire.ZeroKnowledge;\nusing System;\nusing System.IO;\nusing System.Net;\nusing System.Net.Sockets;\nusing System"
},
{
"path": "src/ServiceWire/TcpIp/TcpProxy.cs",
"chars": 1138,
"preview": "using System.Net;\n\nnamespace ServiceWire.TcpIp\n{\n public static class TcpProxy\n {\n public static TInterface"
},
{
"path": "src/ServiceWire/TcpIp/TcpZkEndPoint.cs",
"chars": 586,
"preview": "using System.Net;\n\nnamespace ServiceWire.TcpIp\n{\n public class TcpZkEndPoint\n {\n public string Username { "
},
{
"path": "src/ServiceWire/ZeroKnowledge/IZkRepository.cs",
"chars": 409,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace ServiceWire.ZeroKnowle"
},
{
"path": "src/ServiceWire/ZeroKnowledge/ZkBigInt.cs",
"chars": 47103,
"preview": "/*\n * The MIT License (MIT)\n * Copyright (c) 2007 Scott Garland\n * Permission is hereby granted, free of charge, to any"
},
{
"path": "src/ServiceWire/ZeroKnowledge/ZkCrypto.cs",
"chars": 1777,
"preview": "using System;\nusing System.Security.Cryptography;\n\nnamespace ServiceWire.ZeroKnowledge\n{\n /// <summary>\n /// Easy "
},
{
"path": "src/ServiceWire/ZeroKnowledge/ZkExt.cs",
"chars": 661,
"preview": "using System.Text;\n\nnamespace ServiceWire.ZeroKnowledge\n{\n public static class ZkExt\n {\n public static byte"
},
{
"path": "src/ServiceWire/ZeroKnowledge/ZkPasswordHash.cs",
"chars": 209,
"preview": "namespace ServiceWire.ZeroKnowledge\n{\n public class ZkPasswordHash\n {\n public byte[] Salt { get; set; }\n "
},
{
"path": "src/ServiceWire/ZeroKnowledge/ZkProtocol.cs",
"chars": 6536,
"preview": "using System;\nusing System.Linq;\nusing System.Security.Cryptography;\n\nnamespace ServiceWire.ZeroKnowledge\n{\n /// <su"
},
{
"path": "src/ServiceWire/ZeroKnowledge/ZkSafePrimes.cs",
"chars": 17773,
"preview": "namespace ServiceWire.ZeroKnowledge\n{\n public static class ZkSafePrimes\n {\n public static byte[] N4\n "
},
{
"path": "src/ServiceWire/ZeroKnowledge/ZkSession.cs",
"chars": 3834,
"preview": "using System;\nusing System.Diagnostics;\nusing System.IO;\n\nnamespace ServiceWire.ZeroKnowledge\n{\n public class ZkSess"
},
{
"path": "src/ServiceWire/_license.txt",
"chars": 5877,
"preview": "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n COPYRIGHT NOTICES AND"
},
{
"path": "src/ServiceWire.sln",
"chars": 9489,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.2.3221"
},
{
"path": "src/ServiceWireTestHostPlusClient/Program.cs",
"chars": 1351,
"preview": "// Small Test Program To Debug issues with throwing errors over a channel\nusing System;\nusing ServiceWire.NamedPipes;\n\n"
},
{
"path": "src/ServiceWireTestHostPlusClient/ServiceWireTestHostPlusClient.csproj",
"chars": 762,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup Condition=\" '$(OS)' != 'Windows_NT' \">\n\t\t<TargetFrameworks>net6.0;ne"
},
{
"path": "src/Tests/Integration/ServiceWireTestClient1/App.config",
"chars": 278,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n <appSettings>\n <add key=\"ip\" value=\"127.0.0.1\"/>\n "
},
{
"path": "src/Tests/Integration/ServiceWireTestClient1/Program.cs",
"chars": 5700,
"preview": "using System.Configuration;\nusing System.Net.Sockets;\nusing ServiceWire.NamedPipes;\nusing ServiceWire.TcpIp;\nusing Serv"
},
{
"path": "src/Tests/Integration/ServiceWireTestClient1/ServiceWireTestClient1.csproj",
"chars": 1185,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup Condition=\" '$(OS)' != 'Windows_NT' \">\n\t\t<TargetFrameworks>net6.0;ne"
},
{
"path": "src/Tests/Integration/ServiceWireTestClient2/App.config",
"chars": 278,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n <appSettings>\n <add key=\"ip\" value=\"127.0.0.1\"/>\n "
},
{
"path": "src/Tests/Integration/ServiceWireTestClient2/Program.cs",
"chars": 5558,
"preview": "using System.Configuration;\nusing ServiceWire.NamedPipes;\nusing ServiceWire.TcpIp;\nusing ServiceWireTestCommon;\nusing S"
},
{
"path": "src/Tests/Integration/ServiceWireTestClient2/ServiceWireTestClient2.csproj",
"chars": 1185,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup Condition=\" '$(OS)' != 'Windows_NT' \">\n\t\t<TargetFrameworks>net6.0;ne"
},
{
"path": "src/Tests/Integration/ServiceWireTestHost/App.config",
"chars": 278,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n <appSettings>\n <add key=\"ip\" value=\"127.0.0.1\"/>\n "
},
{
"path": "src/Tests/Integration/ServiceWireTestHost/Program.cs",
"chars": 4105,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Configuration;\nusing System.Net;\nusing System.Text;\nusing "
},
{
"path": "src/Tests/Integration/ServiceWireTestHost/ServiceWireTestHost.csproj",
"chars": 1185,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup Condition=\" '$(OS)' != 'Windows_NT' \">\n\t\t<TargetFrameworks>net6.0;ne"
},
{
"path": "src/Tests/ServiceWireTestCommon/ServiceWireTestCommon.csproj",
"chars": 559,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup Condition=\" '$(OS)' != 'Windows_NT' \">\n\t\t<TargetFrameworks>net6.0;ne"
},
{
"path": "src/Tests/ServiceWireTestCommon/TestContracts.cs",
"chars": 4829,
"preview": "using ServiceWire.NamedPipes;\nusing ServiceWire.TcpIp;\nusing System;\nusing System.Collections.Generic;\nusing System.Net"
},
{
"path": "src/Tests/Unit/ServiceWireTests/AsyncTests.cs",
"chars": 3611,
"preview": "using System;\nusing System.IO;\nusing System.Linq;\nusing System.Text.Json.Serialization;\nusing System.Text.Json;\nusing S"
},
{
"path": "src/Tests/Unit/ServiceWireTests/INetTester.cs",
"chars": 1497,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace ServiceWire"
},
{
"path": "src/Tests/Unit/ServiceWireTests/InterceptionTests.cs",
"chars": 7767,
"preview": "using ServiceWire.Aspects;\nusing System;\nusing System.Diagnostics;\nusing Xunit;\n\nnamespace ServiceWireTests\n{\n publi"
},
{
"path": "src/Tests/Unit/ServiceWireTests/NewtonsoftSerializer.cs",
"chars": 1697,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.IO;\nusing System.Ref"
},
{
"path": "src/Tests/Unit/ServiceWireTests/NpTests.cs",
"chars": 6280,
"preview": "using System;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing ServiceWire.NamedPipes;\nus"
},
{
"path": "src/Tests/Unit/ServiceWireTests/ParameterTransferHelperTests.cs",
"chars": 8087,
"preview": "using ServiceWire;\nusing System;\nusing System.IO;\nusing Xunit;\n\nnamespace ServiceWireTests\n{\n public class Parameter"
},
{
"path": "src/Tests/Unit/ServiceWireTests/ProtobufSerializer.cs",
"chars": 2152,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.IO;\nusing System.Ref"
},
{
"path": "src/Tests/Unit/ServiceWireTests/SequentialCollection.cs",
"chars": 447,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusi"
},
{
"path": "src/Tests/Unit/ServiceWireTests/ServiceWireTests.csproj",
"chars": 1254,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<!-- ** Tests by OS targets only on LTS releases. -->\n\t<PropertyGroup Condition=\" '"
},
{
"path": "src/Tests/Unit/ServiceWireTests/TcpTests.cs",
"chars": 4794,
"preview": "using System;\nusing System.Net;\nusing System.Threading.Tasks;\nusing ServiceWire.TcpIp;\nusing Xunit;\n\nnamespace ServiceW"
},
{
"path": "src/Tests/Unit/ServiceWireTests/TcpZkTests.cs",
"chars": 5247,
"preview": "using System;\nusing System.Net;\nusing System.Threading.Tasks;\nusing ServiceWire.TcpIp;\nusing ServiceWire.ZeroKnowledge;"
},
{
"path": "src/Tests/Unit/ServiceWireTests/ZkProtocolTests.cs",
"chars": 4222,
"preview": "using ServiceWire.ZeroKnowledge;\nusing Xunit;\n\nnamespace ServiceWireTests\n{\n public class ZkProtocolTests\n {\n "
},
{
"path": "src/Tests/testing_readme.txt",
"chars": 610,
"preview": "* * * * * * * * * * * * * * * * *\n* ServiceWire testing readme \n* * * * * * * * * * * * * * * * *\n\nTo run the tests, set"
},
{
"path": "src/output.txt",
"chars": 5812,
"preview": "Build started, please wait...\nBuild started, please wait...\nBuild started, please wait...\nBuild started, please wait...\n"
}
]
About this extraction
This page contains the full source code of the tylerjensen/ServiceWire GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 117 files (384.5 KB), approximately 97.1k tokens, and a symbol index with 606 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.