├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── dotnet.yml ├── .gitignore ├── .vscode ├── launch.json ├── solution-explorer │ ├── class.cs-template │ ├── class.ts-template │ ├── class.vb-template │ ├── default.ts-template │ ├── enum.cs-template │ ├── interface.cs-template │ ├── interface.ts-template │ ├── template-list.json │ └── template-parameters.js └── tasks.json ├── DotBPE.sln ├── LICENSE ├── RELEASE_NOTES.md ├── build ├── releasenotes.props └── version.props ├── docs ├── .$dotbpe.drawio.bkp ├── amp协议.md ├── dotbpe.drawio └── protobuf │ ├── any.proto │ ├── api.proto │ ├── compiler │ └── plugin.proto │ ├── descriptor.proto │ ├── duration.proto │ ├── empty.proto │ ├── field_mask.proto │ ├── source_context.proto │ ├── struct.proto │ ├── timestamp.proto │ ├── type.proto │ └── wrappers.proto ├── icon.png ├── readme.md ├── samples ├── GreeterHttpService │ ├── GreeterHttpService.csproj │ ├── IGreeterService.cs │ ├── ISwaggeSampleService.cs │ ├── Program.cs │ └── Startup.cs ├── MathClient │ ├── MathClient.csproj │ └── Program.cs ├── MathHttpClient │ ├── MathHttpClient.csproj │ ├── Program.cs │ └── Startup.cs ├── MathService.Definition │ ├── Entities.cs │ ├── IMathService.cs │ └── MathService.Definition.csproj └── MathService │ ├── MathService.cs │ ├── MathService.csproj │ └── Program.cs ├── scripts ├── build.sh ├── package_all.sh ├── publish_baseline.sh ├── publish_bestpractice.sh ├── publish_castle.sh ├── publish_consul.sh ├── publish_gateway.sh ├── publish_json.sh ├── publish_jsonnet.sh ├── publish_messagepack.sh ├── publish_pipeline.sh ├── publish_protobuf.sh └── publish_rpc.sh ├── src ├── DotBPE.Baseline │ ├── Collections │ │ ├── ObservableDictionary.cs │ │ ├── SettingsDictionary.cs │ │ └── TagSet.cs │ ├── DotBPE.Baseline.csproj │ ├── Extensions │ │ ├── AddressExtensions.cs │ │ ├── ByteArrayExtensions.cs │ │ ├── CollectionExtensions.cs │ │ ├── ConcurrentQueueExtensions.cs │ │ ├── DateTimeExtensions.cs │ │ ├── EnumHelper.cs │ │ ├── EnumerableExtensions.cs │ │ ├── ExceptionExtensions.cs │ │ ├── FileExtensions.cs │ │ ├── HashExtensions.cs │ │ ├── MimeExtensions.cs │ │ ├── NameValueCollectionExtensions.cs │ │ ├── NumericExtensions.cs │ │ ├── StringExtensions.cs │ │ ├── TaskCompletionSourceExtensions.cs │ │ ├── TaskExtensions.cs │ │ └── TaskFactoryExtensions.cs │ └── Utility │ │ ├── AssemblyDetail.cs │ │ ├── CryptographyManager.cs │ │ ├── IConnectionMapping.cs │ │ ├── ObjectId.cs │ │ └── SingletonBase.cs ├── DotBPE.BestPractice │ ├── AuditLog │ │ ├── AuditJsonFormatter.cs │ │ ├── AuditLogFormatter.cs │ │ └── AuditLogWriter.cs │ ├── Constants │ │ ├── BizErrorCodes.cs │ │ └── ProtocolsConstants.cs │ ├── DotBPE.BestPractice.csproj │ ├── Exceptions │ │ └── BizException.cs │ ├── Extensions │ │ └── ProtobufExtensions.cs │ ├── HostBuilderExtensions.cs │ ├── TaskResult.cs │ └── Utility.cs ├── DotBPE.Extra.Castle │ ├── CallContextServiceActorInterceptor.cs │ ├── ClientInterceptor.cs │ ├── DotBPE.Extra.Castle.csproj │ ├── DynamicClientProxy.cs │ ├── DynamicServiceActorLocator.cs │ ├── Extensions │ │ ├── ClientProxyFactoryExtensions.cs │ │ ├── HostBuilderExtensions.cs │ │ └── ServiceCollectionExtensions.cs │ ├── IRpcServiceInterceptor.cs │ ├── Interceptor.cs │ ├── InvocationContext.cs │ ├── InvokeMeta.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── ReflectionHelper.cs │ ├── RemoteInvokeInterceptor.cs │ ├── ServiceAuditLogInterceptor.cs │ └── ServiceMethod.cs ├── DotBPE.Extra.Json │ ├── ClientProxyFactoryExtensions.cs │ ├── DotBPE.Extra.Json.csproj │ ├── HostBuilderExtensions.cs │ ├── JsonParser.cs │ ├── JsonSerializer.cs │ └── ServiceCollectionExtensions.cs ├── DotBPE.Extra.JsonNet │ ├── ClientProxyFactoryExtensions.cs │ ├── DotBPE.Extra.JsonNet.csproj │ ├── HostBuilderExtensions.cs │ ├── JsonParser.cs │ ├── JsonSerializer.cs │ └── ServiceCollectionExtensions.cs ├── DotBPE.Extra.MessagePack │ ├── ClientProxyFactoryExtensions.cs │ ├── DotBPE.Extra.MessagePack.csproj │ ├── HostBuilderExtensions.cs │ ├── MessagePackSerializer.cs │ └── ServiceCollectionExtensions.cs ├── DotBPE.Extra.Protobuf │ ├── ClientProxyFactoryExtensions.cs │ ├── DotBPE.Extra.Protobuf.csproj │ ├── HostBuilderExtensions.cs │ ├── JsonParser.cs │ ├── ProtobufSerializer.cs │ └── ServiceCollectionExtensions.cs ├── DotBPE.Gateway │ ├── Attributes │ │ └── HttpRouteAttribute.cs │ ├── Contracts │ │ ├── IHttpApiErrorProcess.cs │ │ ├── IHttpApiOutputProcess.cs │ │ ├── IHttpOutputProcessPlugin.cs │ │ ├── IHttpPlugin.cs │ │ ├── IHttpProcessPlugin.cs │ │ ├── IHttpRequestParsePlugin.cs │ │ └── IHttpRequestParsePostPlugin.cs │ ├── DotBPE.Gateway.csproj │ ├── Extensions │ │ ├── ApplicationBuilderExtensions.cs │ │ ├── EndpointRouteBuilderExtensions.cs │ │ ├── HttpRequestExtensions.cs │ │ └── ServiceCollectionExtensions.cs │ ├── HttpApiOption.cs │ ├── HttpVerb.cs │ ├── Internal │ │ ├── ApiEndpointConventionBuilder.cs │ │ ├── ApiMethod.cs │ │ ├── ApiMethodInvoker.cs │ │ ├── ApiMethodModel.cs │ │ ├── ApiMethodProviderContext.cs │ │ ├── ApiProviderServiceBinder.cs │ │ ├── ApiRouteBuilder.cs │ │ ├── DefaultApiMethodProvider.cs │ │ ├── HttpApiCallHandler.cs │ │ ├── HttpApiMetadata.cs │ │ ├── IApiMethodProvider.cs │ │ ├── RequestEncoding.cs │ │ └── ResponseEncoding.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── RpcGatewayOption.cs │ └── Swagger │ │ ├── ApiModelMetadata.cs │ │ ├── DefaultSwaggerProvider.cs │ │ ├── HttpApiDescriptionProvider.cs │ │ ├── ISwaggerProvider.cs │ │ ├── Models │ │ ├── SwaggerApiContactInfo.cs │ │ ├── SwaggerApiInfo.cs │ │ ├── SwaggerApiParameters.cs │ │ ├── SwaggerApiResponse.cs │ │ ├── SwaggerDefinition.cs │ │ ├── SwaggerInfo.cs │ │ ├── SwaggerItemSchema.cs │ │ ├── SwaggerMethod.cs │ │ └── SwaggerPropertyDefinition.cs │ │ ├── SwaggerMiddleware.cs │ │ ├── SwaggerOptions.cs │ │ ├── SwaggerUIMiddleware.cs │ │ ├── SwaggerUIOptions.cs │ │ ├── UI │ │ ├── DebugContent.3b78e7fd.js │ │ ├── DebugContent.a773311c.css │ │ ├── favicon.7cc1a2af.svg │ │ ├── index.57a718f9.js │ │ ├── index.6d96fa03.css │ │ ├── index.html │ │ ├── react-venders.a651e260.js │ │ └── v2 │ │ │ └── swagger.json │ │ └── XmlComments │ │ ├── XmlCommentResolver.cs │ │ ├── XmlCommentsMemberNameHelper.cs │ │ └── XmlCommentsTextHelper.cs └── DotBPE.Rpc │ ├── Attributes │ ├── RpcMethodAttribute.cs │ └── RpcServiceAttribute.cs │ ├── AuditLog │ ├── AuditLogger.cs │ ├── IAuditLogFormatter.cs │ ├── IAuditLogInfo.cs │ ├── IAuditLogWriter.cs │ ├── IAuditLogger.cs │ └── IAuditLoggerFactory.cs │ ├── Client │ ├── ClientProxyFactory.cs │ ├── ICallInvoker.cs │ ├── IClientMessageHandler.cs │ ├── IClientProxy.cs │ ├── IClientProxyFactory.cs │ ├── IMessageSubscriber.cs │ ├── IMessageSubscriberContainer.cs │ ├── IRouterPoint.cs │ ├── IRoutingPolicy.cs │ ├── IRpcClient.cs │ ├── IServiceRouter.cs │ ├── ITransport.cs │ ├── ITransportFactory.cs │ ├── Impl │ │ ├── DefaultCallInvoker.cs │ │ ├── DefaultClientMessageHandler.cs │ │ ├── DefaultMessageSubscriberContainer.cs │ │ ├── DefaultRpcClient.cs │ │ ├── DefaultServiceRouter.cs │ │ ├── DefaultTransport.cs │ │ ├── DefaultTransportFactory.cs │ │ └── RpcSocketClient.cs │ └── RoutingPolicies │ │ ├── RandomRoutingPolicy.cs │ │ ├── RoundrobinRoutingPolicy.cs │ │ └── WeightedRoundRobinRoutingPolicy.cs │ ├── Codec │ ├── CodecType.cs │ └── ISerializer.cs │ ├── DotBPE.Rpc.csproj │ ├── Exceptions │ ├── RpcCodecException.cs │ ├── RpcCommunicationException.cs │ └── RpcException.cs │ ├── Extensions │ ├── ClientProxyFactoryExtensions.cs │ ├── HostBuilderExtensions.cs │ └── ServiceCollectionExtensions.cs │ ├── Hosting │ ├── AmpPeachSocketService.cs │ ├── PeachServerBootstrap.cs │ ├── PeachServerHost.cs │ ├── RpcServerOptions.cs │ └── RpcServiceHostedService.cs │ ├── IJsonParser.cs │ ├── IMethod.cs │ ├── IRpcContext.cs │ ├── Internal │ ├── HeartBeatServiceActor.cs │ ├── HeartBeatServiceActorHandler.cs │ ├── NotFoundServiceActor.cs │ └── NotFoundServiceActorHandler.cs │ ├── Method.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Protocols │ ├── AmpChannelHandlerPipeline.cs │ ├── AmpDecodeHandler.cs │ ├── AmpEncodeHandler.cs │ ├── AmpMessage.cs │ ├── AmpProtocol.cs │ ├── IRpcMessage.cs │ └── RpcStatusCodes.cs │ ├── RouterPointOptions.cs │ ├── RpcClientOptions.cs │ ├── RpcResult.cs │ ├── Server │ ├── ActorInvokerModel.cs │ ├── ICallContext.cs │ ├── IContextAccessor.cs │ ├── IMessageHandler.cs │ ├── IServerHost.cs │ ├── IServiceActor.cs │ ├── IServiceActorBuilder.cs │ ├── IServiceActorHandler.cs │ ├── IServiceActorHandlerFactory.cs │ ├── IServiceActorLocator.cs │ ├── IServiceActorProvider.cs │ ├── Impl │ │ ├── ActorCallHandler.cs │ │ ├── BaseService.cs │ │ ├── DefaultMessageHandler.cs │ │ ├── DefaultServiceActorHandlerFactory.cs │ │ ├── DefaultServiceActorLocator.cs │ │ ├── MethodInvoker.cs │ │ ├── RpcContext.cs │ │ ├── ServerMethod.cs │ │ └── ServiceActorHandler.cs │ ├── RequestDelegate.cs │ ├── ServiceActorBinder.cs │ ├── ServiceActorProvider.cs │ └── ServiceActorProviderContext.cs │ ├── ServiceModel.cs │ └── Utils │ └── EndPointParser.cs └── tests ├── DotBPE.Extra.Castle.Tests ├── ClientInterceptorTest.cs ├── DotBPE.Extra.Castle.Tests.csproj ├── DynamicClientProxyTests.cs ├── ServiceActorInterceptorTests.cs └── TestObjects │ └── LogInterceptor.cs ├── DotBPE.Gateway.Tests ├── DefaultApiMethodProviderTests.cs ├── DotBPE.Gateway.Tests.csproj ├── HttpApiCallHandlerTests.cs ├── ServiceExtensionsTests.cs └── TestObjects │ ├── DefaultJsonSerializer.cs │ ├── IInvalidPatternTestService.cs │ └── TestGreetService.cs ├── DotBPE.Rpc.Tests ├── Client │ ├── ClientProxyFactoryTests.cs │ ├── DefaultCallInvokerTests.cs │ ├── DefaultClientMessageHandlerTests.cs │ ├── DefaultMessageSubscriberContainerTests.cs │ ├── DefaultRpcClientTests.cs │ └── DefaultTransportFactoryTests.cs ├── DotBPE.Rpc.Tests.csproj ├── Hosting │ └── PeachServerHostTest.cs ├── Protocols │ └── AmpProtocolTests.cs └── Server │ ├── DefaultMessageHandlerTests.cs │ ├── DefaultServiceActorHandlerFactoryTests.cs │ └── DefaultServiceActorLocatorTests.cs └── DotBPE.TestBase ├── DotBPE.TestBase.csproj ├── Services ├── FooService.cs └── IFooService.cs └── TextJsonSerializer.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | *.doc diff=astextplain 2 | *.DOC diff=astextplain 3 | *.docx diff=astextplain 4 | *.DOCX diff=astextplain 5 | *.dot diff=astextplain 6 | *.DOT diff=astextplain 7 | *.pdf diff=astextplain 8 | *.PDF diff=astextplain 9 | *.rtf diff=astextplain 10 | *.RTF diff=astextplain 11 | *.jpg binary 12 | *.png binary 13 | *.gif binary 14 | *.cs text=auto diff=csharp 15 | *.vb text=auto 16 | *.resx text=auto 17 | *.c text=auto 18 | *.cpp text=auto 19 | *.cxx text=auto 20 | *.h text=auto 21 | *.hxx text=auto 22 | *.py text=auto 23 | *.rb text=auto 24 | *.java text=auto 25 | *.html text=auto 26 | *.htm text=auto 27 | *.css text=auto 28 | *.scss text=auto 29 | *.sass text=auto 30 | *.less text=auto 31 | *.js text=auto 32 | *.lisp text=auto 33 | *.clj text=auto 34 | *.sql text=auto 35 | *.php text=auto 36 | *.lua text=auto 37 | *.m text=auto 38 | *.asm text=auto 39 | *.erl text=auto 40 | *.fs text=auto 41 | *.fsx text=auto 42 | *.hs text=auto 43 | *.csproj text=auto 44 | *.vbproj text=auto 45 | *.fsproj text=auto 46 | *.dbproj text=auto 47 | *.sln text=auto eol=crlf -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a .NET project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net 3 | 4 | name: .NET 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Setup .NET 20 | uses: actions/setup-dotnet@v4 21 | with: 22 | dotnet-version: 8.0.x 23 | - name: Restore dependencies 24 | run: dotnet restore 25 | - name: Build 26 | run: dotnet build --no-restore 27 | - name: Test 28 | run: dotnet test --no-build --verbosity normal 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj/ 2 | [Bb]in/ 3 | TestResults/ 4 | .nuget/ 5 | _ReSharper.*/ 6 | packages/ 7 | artifacts/ 8 | PublishProfiles/ 9 | *.user 10 | *.suo 11 | *.cache 12 | *.docstates 13 | _ReSharper.* 14 | nuget.exe 15 | *net45.csproj 16 | *net451.csproj 17 | *k10.csproj 18 | *.psess 19 | *.vsp 20 | *.pidb 21 | *.userprefs 22 | *DS_Store 23 | *.ncrunchsolution 24 | *.*sdf 25 | *.ipch 26 | *.sln.ide 27 | *.sublime-workspace 28 | node_modules/ 29 | node_modules1/ 30 | node_modules2/ 31 | .build/ 32 | logs/ 33 | typings/ 34 | project.lock.json 35 | classes 36 | data 37 | temp 38 | doc/site 39 | dist 40 | # Logs 41 | logs 42 | *.log 43 | npm-debug.log* 44 | # Runtime data 45 | pids 46 | *.pid 47 | *.seed 48 | # Directory for instrumented libs generated by jscoverage/JSCover 49 | lib-cov 50 | # Coverage directory used by tools like istanbul 51 | coverage 52 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 53 | .grunt 54 | # node-waf configuration 55 | .lock-wscript 56 | # Compiled binary addons (http://nodejs.org/api/addons.html) 57 | build/Release 58 | # Dependency directory 59 | node_modules 60 | # Optional npm cache directory 61 | .npm 62 | # Optional REPL history 63 | .node_repl_history 64 | cache/ 65 | .vs/ 66 | *.lnk 67 | *.Production.json 68 | .idea/ 69 | .vscode/ 70 | workspace.xml 71 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (console)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/src/sample/06-gateway-aspnet/GatewayForAspNet/bin/Debug/netcoreapp2.0/GatewayForAspNet.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/src/sample/06-gateway-aspnet/GatewayForAspNet", 16 | // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window 17 | "console": "internalConsole", 18 | "stopAtEntry": false, 19 | "internalConsoleOptions": "openOnSessionStart" 20 | }, 21 | { 22 | "name": ".NET Core Attach", 23 | "type": "coreclr", 24 | "request": "attach", 25 | "processId": "${command:pickProcess}" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /.vscode/solution-explorer/class.cs-template: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace {{namespace}} 4 | { 5 | public class {{name}} 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/solution-explorer/class.ts-template: -------------------------------------------------------------------------------- 1 | export class {{name}} { 2 | 3 | } -------------------------------------------------------------------------------- /.vscode/solution-explorer/class.vb-template: -------------------------------------------------------------------------------- 1 | Imports System 2 | 3 | Namespace {{namespace}} 4 | 5 | Public Class {{name}} 6 | 7 | End Class 8 | 9 | End Namespace 10 | -------------------------------------------------------------------------------- /.vscode/solution-explorer/default.ts-template: -------------------------------------------------------------------------------- 1 | export default {{name}} { 2 | 3 | } -------------------------------------------------------------------------------- /.vscode/solution-explorer/enum.cs-template: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace {{namespace}} 4 | { 5 | public enum {{name}} 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/solution-explorer/interface.cs-template: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace {{namespace}} 4 | { 5 | public interface {{name}} 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/solution-explorer/interface.ts-template: -------------------------------------------------------------------------------- 1 | export interface {{name}} { 2 | 3 | } -------------------------------------------------------------------------------- /.vscode/solution-explorer/template-list.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates": [ 3 | { 4 | "name": "Class", 5 | "extension": "cs", 6 | "file": "./class.cs-template", 7 | "parameters": "./template-parameters.js" 8 | }, 9 | { 10 | "name": "Interface", 11 | "extension": "cs", 12 | "file": "./interface.cs-template", 13 | "parameters": "./template-parameters.js" 14 | }, 15 | { 16 | "name": "Enum", 17 | "extension": "cs", 18 | "file": "./enum.cs-template", 19 | "parameters": "./template-parameters.js" 20 | }, 21 | { 22 | "name": "Class", 23 | "extension": "ts", 24 | "file": "./class.ts-template", 25 | "parameters": "./template-parameters.js" 26 | }, 27 | { 28 | "name": "Interface", 29 | "extension": "ts", 30 | "file": "./interface.ts-template", 31 | "parameters": "./template-parameters.js" 32 | }, 33 | { 34 | "name": "Default", 35 | "extension": "ts", 36 | "file": "./default.ts-template", 37 | "parameters": "./template-parameters.js" 38 | }, 39 | { 40 | "name": "Class", 41 | "extension": "vb", 42 | "file": "./class.vb-template", 43 | "parameters": "./template-parameters.js" 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /.vscode/solution-explorer/template-parameters.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | 3 | module.exports = function(filename, projectPath, folderPath) { 4 | var namespace = "Unknown"; 5 | if (projectPath) { 6 | namespace = path.basename(projectPath, path.extname(projectPath)); 7 | if (folderPath) { 8 | namespace += "." + folderPath.replace(path.dirname(projectPath), "").substring(1).replace(/[\\\/]/g, "."); 9 | } 10 | } 11 | 12 | return { 13 | namespace: namespace, 14 | name: path.basename(filename, path.extname(filename)) 15 | } 16 | }; -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "taskName": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/src/sample/06-gateway-aspnet/GatewayForAspNet/GatewayForAspNet.csproj" 11 | ], 12 | "problemMatcher": "$msCompile" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 xuanye wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RELEASE_NOTES.md: -------------------------------------------------------------------------------- 1 | 2 | #### 2.0.5 Feb 21, 2019 3 | 1. 修复心跳包服务端没有正确返回的问题 4 | 2. 修复网关处理Post Json时,部分数据丢失的问题 5 | 3. 新增动态调用反射帮助类,支持动态调用,方便测试 6 | 4. 修复审计日志没有正确记录的问题 7 | 5. 修复其他已知的问题 8 | 9 | 10 | #### 2.0.0 Jan 30, 2019 11 | 1. 重构框架,分离通信相关的代码 12 | 2. 支持本地和远端服务自动调度 13 | 3. 服务注册和发现(可选) 14 | 4. 支持多种路由方式(可选) 15 | 5. 支持依赖注入和AOP 16 | 6. 支持服务分组 17 | 7. 轻量级的Http网关 18 | 8. 支持多种服务声明方式,接口或者服务描述文件 19 | 9. 多种序列化方式:Protobuf、MessagePack、JSON 20 | -------------------------------------------------------------------------------- /build/releasenotes.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 1. 添加时间格式化一般字符串表示法的扩展方法 7 | 8 | 9 | 1. 调整TargetFramework 为 netstandard2.0,去除不必要的升级 10 | 2. 扫描注入的接口新增了Host绑定的服务分组参数,用于区分注册服务 11 | 3. 修复心跳包时长问题导致的长连接一直断开的问题 12 | 4. 升级Peach到0.2.2,解决某些网络环境下,无法获取到内网IP,导致绑定地址错误 13 | 14 | 15 | 1. 优化代码逻辑 16 | 2. 添加客户端和服务器端拦截器的实现 17 | 18 | 19 | 20 | 1. 调整TargetFramework 为 netstandard2.0,去除不必要的升级 21 | 22 | 23 | 1. 实现System.Text.Json的编解码实现 24 | 25 | 26 | 1. 调整TargetFramework 为 netstandard2.0,去除不必要的升级 27 | 28 | 29 | 1. 调整TargetFramework 为 netstandard2.0,去除不必要的升级 30 | 31 | 32 | 1. 新增绑定到IWebHost的RPC服务,主要用于测试 33 | 2. 重构Gateway,参考gRPC的绑定方式 34 | 3. 合并Swagger相关的内容到Gateway项目中 35 | 4. 更新自定义SwaggerUI 36 | 37 | 38 | 1. 移除不必要的引用 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /build/version.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 3.0.2 4 | 1.0.2 5 | 3.0.3 6 | 1.0.1 7 | 3.0.0 8 | 3.0.0 9 | 3.0.0 10 | 3.0.1 11 | 3.0.2 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/amp协议.md: -------------------------------------------------------------------------------- 1 | ### AMP协议说明 版本0 2 | 3 | ``` 4 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14151617 -18 5 | +------------+----------+---------+------+-------+---------+---------+------------+ 6 | | | | ||| | | | 7 | +------------+----------+---------+------+-------+---------+---------+------------+ 8 | ``` 9 | 10 | + ver/argc = 版本 固定填0 11 | + length = 为总包长 12 | + seq = 请求序列号 13 | + type = 消息类型 14 | * 1 = Request 请求消息 15 | * 2 = Response 响应消息 16 | * 3 = Notify 通知消息 17 | + serId = serviceId 服务号 18 | + msgId = msgId 消息ID 19 | + code = 当 type = 0 (请求时)固定传0 ,其他即为响应码,如果响应码不为0 则认为请求失败,具体错误码再定义 20 | + data = 实际的业务数据 21 | 22 | 23 | ### AMP协议说明 版本1 24 | 25 | ``` 26 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 1415 16171819 20 -21 27 | +------------+----------+---------+------+-------------+---------+---------+--------+------------+ 28 | | | | || | | | | | 29 | +------------+----------+---------+------+-------------+---------+---------+--------+------------+ 30 | ``` 31 | 32 | + ver/argc = 版本 固定填1 33 | + length = 为总包长 34 | + seq = 请求序列号 35 | + type = 消息类型 36 | * 1 = Request 请求消息 37 | * 2 = Response 响应消息 38 | * 3 = Notify 通知消息 39 | * 4 = InvokeWithoutResponse 调用不关心返回值 40 | + serId = serviceId 服务号 41 | + msgId = msgId 消息ID 42 | + code = 当 type = 0 (请求时)固定传0 ,其他即为响应码,如果响应码不为0 则认为请求失败,具体错误码再定义 43 | + codecType = 编码方式 0=默认 Protobuf 1=MessagePack 2=JSON 44 | + data = 实际的业务数据 45 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuanye/dotbpe/5f25603a96ac9f69e6e47461145cd81c10682d35/icon.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | dotbpe 2 | ------------- 3 | 4 | dotbpe一套基于dotnet core平台的业务流程处理引擎,力求解决项目开发中,关于服务端开发的各种通用问题,如远程过程调用(Rpc),延迟队列(DelayTaskQueue),任务调度(TaskManage),网关(Gateway)等问题。 5 | 6 | dotbpe rpc 项目就是其中的Rpc部分的实现,底层的通讯部份基于[Peach](https://github.com/xuanye/peach)(基于DotNetty封装,支持自定义协议的Socket类库)。该组件的目标并不是只是解决Rpc的问题,同时考虑到开发调式的便利性,支持本地服务和远端无差别开发,在编码时不用考虑服务是如何部署的(分布式或者单机部署),可以在项目初期流量较少时,只部署单台或者做简单的负载均衡即可,当项目流量增加后可通过配置和部署方案,不需要修改任何代码来实现快速扩容。 7 | 8 | dotbpe rpc 支持两种开发模式,一种类似于Dubbo的定义接口的方式Rpc服务,另外一种支持像gRpc方式,预先定义服务描述文件(.proto)来定义Rpc服务. 9 | > Note: 在同一个项目中应规范只使用一种,如无特殊情况,应避免交叉使用 10 | 11 | 12 | ## Features 13 | 14 | - 高性能,易于使用的分布式远程调用框架 15 | - 支持本地和远端服务自动调度 16 | - 服务治理功能 17 | - 注册中心(可选) 18 | - 失败重试方式(可选) 19 | - 支持多种路由方式(可选) 20 | - 支持依赖注入和AOP 21 | - 支持服务分组 22 | - 轻量级的Http网关 23 | - 快速测试工具 24 | - 支持服务声明方式 25 | - 使用C#代码定义接口方式,类似Dubbo 26 | - 使用proto文件定义,类似gRpc (使用该方式则序列化只能使用Protobuf) 27 | - 多种序列化方式(不能混合使用) 28 | - Protobuf 29 | - MessagePack 30 | - JSON 31 | - 支持多个扩展点 32 | 33 | 34 | ## 二进制协议说明 35 | 36 | ``` 37 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 1415 16171819 20 -21 38 | +------------+----------+---------+------+-------------+---------+---------+--------+------------+ 39 | | | | || | | | | | 40 | +------------+----------+---------+------+-------------+---------+---------+--------+------------+ 41 | ``` 42 | 43 | + ver/argc = 版本 固定填1 44 | + length = 为总包长 45 | + seq = 请求序列号 46 | + type = 消息类型 47 | * 1 = Request 请求消息 48 | * 2 = Response 响应消息 49 | * 3 = Notify 通知消息 50 | * 4 = InvokeWithoutResponse 调用不关心返回值 51 | + serId = serviceId 服务号 52 | + msgId = msgId 消息ID 53 | + code = 当 type = 0 (请求时)固定传0 ,其他即为响应码,如果响应码不为0 则认为请求失败,具体错误码再定义 54 | + codecType = 编码方式 0=默认 Protobuf 1=MessagePack 2=JSON 55 | + data = 实际的业务数据 56 | -------------------------------------------------------------------------------- /samples/GreeterHttpService/GreeterHttpService.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | true 7 | $(NoWarn);1591 8 | win10-x64;centos.7-x64 9 | 100 10 | 100 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /samples/GreeterHttpService/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Logging; 4 | using System.Threading; 5 | 6 | namespace GreeterHttpService 7 | { 8 | static class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | ThreadPool.SetMinThreads(100, 100); 13 | BuildWebHost(args).Run(); 14 | } 15 | 16 | static IWebHost BuildWebHost(string[] args) => 17 | WebHost.CreateDefaultBuilder(args) 18 | .UseUrls("http://*:5560") //HTTP绑定在5560端口 19 | .UseStartup() 20 | .ConfigureLogging(builder => { builder.SetMinimumLevel(LogLevel.Warning); }) 21 | .Build(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/MathClient/MathClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/MathHttpClient/MathHttpClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net5.0 6 | true 7 | $(NoWarn);1591 8 | win10-x64;centos.7-x64 9 | 100 10 | 100 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /samples/MathHttpClient/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using Microsoft.AspNetCore; 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace MathHttpClient 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | ThreadPool.SetMinThreads(100, 100); 14 | BuildWebHost(args).Run(); 15 | } 16 | 17 | static IWebHost BuildWebHost(string[] args) => 18 | WebHost.CreateDefaultBuilder(args) 19 | .UseUrls("http://*:5561") //HTTP绑定在6200端口 20 | .UseStartup() 21 | .ConfigureLogging(builder => { builder.SetMinimumLevel(LogLevel.Debug); }) 22 | .Build(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /samples/MathHttpClient/Startup.cs: -------------------------------------------------------------------------------- 1 | using DotBPE.Extra; 2 | using DotBPE.Gateway; 3 | using DotBPE.Rpc.Config; 4 | using MathService.Definition; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Routing; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using IConfiguration = Microsoft.Extensions.Configuration.IConfiguration; 10 | 11 | namespace MathHttpClient 12 | { 13 | public class Startup 14 | { 15 | public Startup(IConfiguration config) 16 | { 17 | this.Configuration = config; 18 | } 19 | 20 | IConfiguration Configuration { get; } 21 | 22 | // This method gets called by the runtime. Use this method to add services to the container. 23 | public void ConfigureServices(IServiceCollection services) 24 | { 25 | services.Configure(router => 26 | { 27 | router.Categories.Add(new GroupIdentifierOption 28 | { 29 | GroupName = "default", 30 | RemoteAddress = Peach.Infrastructure.IPUtility.GetLocalIntranetIP()+":5566" 31 | }); 32 | }); 33 | 34 | 35 | services.AddMessagePackSerializer(); //message pack serializer 36 | services.AddJsonNetParser(); // http result json parser 37 | services.AddDynamicClientProxy(); // aop client 38 | services.AddDynamicServiceProxy(); // aop service 39 | 40 | services.AddDotBPEHttpApi(); 41 | 42 | } 43 | 44 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 45 | public void Configure(IApplicationBuilder app) 46 | { 47 | app.UseRouting(); 48 | app.UseEndpoints(endpoints => { 49 | 50 | endpoints.MapService(); 51 | 52 | endpoints.MapGet("/", async context => 53 | { 54 | await context.Response.WriteAsync("Welcome to DotBPE RPC Service."); 55 | }); 56 | }); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /samples/MathService.Definition/Entities.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Runtime.Serialization; 5 | 6 | namespace MathService.Definition 7 | { 8 | /// 9 | /// 加法返回值 10 | /// 11 | [DataContract] 12 | public class SumRes 13 | { 14 | /// 15 | /// 总记录 16 | /// 17 | [DataMember(Order = 1, Name = "total")] 18 | public int Total { get; set; } 19 | 20 | } 21 | 22 | /// 23 | /// 加法请求 24 | /// 25 | [DataContract] 26 | public class SumReq 27 | { 28 | /// 29 | /// 字段A 30 | /// 31 | [DataMember(Order = 1, Name = "a")] 32 | public int A { get; set; } 33 | 34 | /// 35 | /// 字段B 36 | /// 37 | [DataMember(Order = 2, Name = "b")] 38 | public int B { get; set; } 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /samples/MathService.Definition/IMathService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using System.Threading.Tasks; 6 | 7 | namespace MathService.Definition 8 | { 9 | /// 10 | /// 数学服务 11 | /// 12 | [RpcService(100)] 13 | public interface IMathService 14 | { 15 | /// 16 | /// 加法服务 17 | /// 18 | /// 请求参数req 19 | /// 返回值Res 20 | [RpcMethod(1)] 21 | Task> SumAsync(SumReq req); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/MathService.Definition/MathService.Definition.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | true 6 | $(NoWarn);1591 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/MathService/MathService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using DotBPE.Rpc.Server; 6 | using MathService.Definition; 7 | using Microsoft.Extensions.Logging; 8 | using System.Threading.Tasks; 9 | 10 | namespace MathService 11 | { 12 | public class MathService : BaseService, IMathService 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public MathService(ILogger logger) 17 | { 18 | _logger = logger; 19 | } 20 | public Task> SumAsync(SumReq req) 21 | { 22 | var result = new RpcResult { Data = new SumRes() }; 23 | result.Data.Total = req.A + req.B; 24 | 25 | _logger.LogInformation("A+B=C {A}+{B}={C}", req.A, req.B, result.Data.Total); 26 | 27 | return Task.FromResult(result); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /samples/MathService/MathService.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | win10-x64;centos.7-x64 7 | 100 8 | 100 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /samples/MathService/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Extra; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Hosting; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace MathService 10 | { 11 | static class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | var builder = new HostBuilder() 16 | .UseRpcServer() 17 | .UseCastleDynamicProxy() 18 | .UseMessagePackSerializer() 19 | .BindService() 20 | .ConfigureLogging( 21 | logger => 22 | { 23 | logger.SetMinimumLevel(LogLevel.Debug); 24 | logger.AddConsole(); 25 | } 26 | ); 27 | 28 | //启动 29 | builder.RunServerAsync().GetAwaiter().GetResult(); 30 | 31 | 32 | /* 33 | * Consul Service Registration 34 | * 35 | var builder = new HostBuilder() 36 | .UseRpcServer() 37 | .UseCastleDynamicProxy() 38 | .UseMessagePack() 39 | .BindService() 40 | //.BindServices(services => { services.Add();}) 41 | .UseConsulServiceRegistration((point, list) => 42 | { 43 | var tcpCheck = new AgentServiceCheck 44 | { 45 | DeregisterCriticalServiceAfter = 1.Minutes(), 46 | Interval = 30.Seconds(), 47 | TCP = EndPointParser.ParseEndPointToString(point.RemoteAddress) 48 | }; 49 | list.Add(tcpCheck); 50 | }) //添加服务注册的依赖 51 | .ConfigureLogging( 52 | logger => 53 | { 54 | logger.AddConsole(); 55 | } 56 | ); 57 | 58 | //启动 59 | builder.RegisterAndRunConsoleAsync().Wait(); 60 | */ 61 | 62 | 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet restore ./DotBPE.sln 14 | dotnet build ./DotBPE.sln -c Release 15 | -------------------------------------------------------------------------------- /scripts/package_all.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet restore ./DotBPE.sln 14 | dotnet build ./DotBPE.sln -c Release 15 | 16 | dotnet pack ./src/DotBPE.Baseline/DotBPE.Baseline.csproj -c Release -o $artifactsFolder 17 | dotnet pack ./src/DotBPE.Extra.Castle/DotBPE.Extra.Castle.csproj -c Release -o $artifactsFolder 18 | dotnet pack ./src/DotBPE.Extra.JsonNet/DotBPE.Extra.JsonNet.csproj -c Release -o $artifactsFolder 19 | dotnet pack ./src/DotBPE.Extra.MessagePack/DotBPE.Extra.MessagePack.csproj -c Release -o $artifactsFolder 20 | dotnet pack ./src/DotBPE.Extra.Protobuf/DotBPE.Extra.Protobuf.csproj -c Release -o $artifactsFolder 21 | dotnet pack ./src/DotBPE.Extra.Json/DotBPE.Extra.Json.csproj -c Release -o $artifactsFolder 22 | dotnet pack ./src/DotBPE.Gateway/DotBPE.Gateway.csproj -c Release -o $artifactsFolder 23 | dotnet pack ./src/DotBPE.Rpc/DotBPE.Rpc.csproj -c Release -o $artifactsFolder 24 | dotnet pack ./src/DotBPE.BestPractice/DotBPE.BestPractice.csproj -c Release -o $artifactsFolder 25 | 26 | -------------------------------------------------------------------------------- /scripts/publish_baseline.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.Baseline/DotBPE.Baseline.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.Baseline/DotBPE.Baseline.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.Baseline.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /scripts/publish_bestpractice.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.BestPractice/DotBPE.BestPractice.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.BestPractice/DotBPE.BestPractice.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.BestPractice.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /scripts/publish_castle.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.Extra.Castle/DotBPE.Extra.Castle.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.Extra.Castle/DotBPE.Extra.Castle.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.Extra.Castle.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /scripts/publish_consul.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.Extra.Consul/DotBPE.Extra.Consul.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.Extra.Consul/DotBPE.Extra.Consul.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.Extra.Consul.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /scripts/publish_gateway.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | 14 | dotnet build ./src/DotBPE.Gateway/DotBPE.Gateway.csproj -c Release 15 | 16 | dotnet pack ./src/DotBPE.Gateway/DotBPE.Gateway.csproj -c Release -o $artifactsFolder 17 | 18 | dotnet nuget push ./$artifactsFolder/DotBPE.Gateway.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 19 | -------------------------------------------------------------------------------- /scripts/publish_json.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.Extra.Json/DotBPE.Extra.Json.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.Extra.Json/DotBPE.Extra.Json.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.Extra.Json.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /scripts/publish_jsonnet.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.Extra.JsonNet/DotBPE.Extra.JsonNet.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.Extra.JsonNet/DotBPE.Extra.JsonNet.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.Extra.JsonNet.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /scripts/publish_messagepack.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.Extra.MessagePack/DotBPE.Extra.MessagePack.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.Extra.MessagePack/DotBPE.Extra.MessagePack.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.Extra.MessagePack.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /scripts/publish_pipeline.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.Extra.Pipeline/DotBPE.Extra.Pipeline.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.Extra.Pipeline/DotBPE.Extra.Pipeline.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.Extra.Pipeline.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /scripts/publish_protobuf.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.Extra.Protobuf/DotBPE.Extra.Protobuf.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.Extra.Protobuf/DotBPE.Extra.Protobuf.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.Extra.Protobuf.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /scripts/publish_rpc.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | cd $(dirname $0)/../ 4 | 5 | artifactsFolder="./artifacts" 6 | 7 | if [ -d $artifactsFolder ]; then 8 | rm -R $artifactsFolder 9 | fi 10 | 11 | mkdir -p $artifactsFolder 12 | 13 | dotnet build ./src/DotBPE.Rpc/DotBPE.Rpc.csproj -c Release 14 | 15 | dotnet pack ./src/DotBPE.Rpc/DotBPE.Rpc.csproj -c Release -o $artifactsFolder 16 | 17 | dotnet nuget push ./$artifactsFolder/DotBPE.Rpc.*.nupkg -k $NUGET_KEY -s https://www.nuget.org 18 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Collections/TagSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace DotBPE.Baseline.Collections 5 | { 6 | public class TagSet : HashSet 7 | { 8 | public TagSet() : base(StringComparer.OrdinalIgnoreCase) 9 | { 10 | } 11 | 12 | public TagSet(IEnumerable values) 13 | : base(StringComparer.OrdinalIgnoreCase) 14 | { 15 | foreach (string value in values) 16 | Add(value); 17 | } 18 | 19 | public new IDisposable Add(string item) 20 | { 21 | base.Add(item); 22 | return new DisposableTag(this, item); 23 | } 24 | 25 | private class DisposableTag : IDisposable 26 | { 27 | private readonly TagSet _items; 28 | 29 | public DisposableTag(TagSet items, string value) 30 | { 31 | this._items = items; 32 | Value = value; 33 | } 34 | 35 | public string Value { get; private set; } 36 | 37 | public void Dispose() 38 | { 39 | if (this._items.Contains(Value)) this._items.Remove(Value); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/DotBPE.Baseline.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | netstandard2.0 6 | $(BaselinePackageVersion) 7 | Xuanye Wong 8 | Xuanye Wong 9 | microservice,dotnet,peach,rpc,dotbpe,baseline 10 | icon.png 11 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 12 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 13 | https://github.com/dotbpe/dotbpe 14 | https://raw.githubusercontent.com/dotbpe/dotbpe/master/LICENSE 15 | https://github.com/dotbpe/dotbpe.git 16 | git 17 | 18 | $(BaselinePackageNotes) 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Extensions/AddressExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace DotBPE.Baseline.Extensions 4 | { 5 | public static class AddressExtensions 6 | { 7 | 8 | public static string ToIPV4(this IPAddress address) 9 | { 10 | if (address.IsIPv4MappedToIPv6) 11 | { 12 | return address.MapToIPv4().ToString(); 13 | } 14 | 15 | return address.ToString(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Extensions/ByteArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.IO.Compression; 4 | 5 | namespace DotBPE.Baseline.Extensions 6 | { 7 | public static class ByteArrayExtensions 8 | { 9 | public static byte[] Decompress(this byte[] data, string encoding) 10 | { 11 | byte[] decompressedData = null; 12 | using (var outputStream = new MemoryStream()) 13 | { 14 | using (var inputStream = new MemoryStream(data)) 15 | { 16 | if (encoding == "gzip") 17 | using (var zip = new GZipStream(inputStream, CompressionMode.Decompress)) 18 | { 19 | zip.CopyTo(outputStream); 20 | } 21 | else if (encoding == "deflate") 22 | using (var zip = new DeflateStream(inputStream, CompressionMode.Decompress)) 23 | { 24 | zip.CopyTo(outputStream); 25 | } 26 | else 27 | throw new ArgumentException(String.Format("Unsupported encoding type \"{0}\".", encoding), "encoding"); 28 | } 29 | 30 | decompressedData = outputStream.ToArray(); 31 | } 32 | 33 | return decompressedData; 34 | } 35 | 36 | public static byte[] Compress(this byte[] data) 37 | { 38 | byte[] compressesData; 39 | using (var outputStream = new MemoryStream()) 40 | { 41 | using (var zip = new GZipStream(outputStream, CompressionMode.Compress)) 42 | { 43 | zip.Write(data, 0, data.Length); 44 | } 45 | 46 | compressesData = outputStream.ToArray(); 47 | } 48 | 49 | return compressesData; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Extensions/CollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | 5 | 6 | namespace DotBPE.Baseline.Extensions 7 | { 8 | public static class CollectionExtensions 9 | { 10 | public static void RemoveAll(this ICollection list, IEnumerable items) 11 | { 12 | foreach (var i in items.ToList()) 13 | list.Remove(i); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Extensions/ConcurrentQueueExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | 3 | namespace DotBPE.Baseline.Extensions 4 | { 5 | public static class ConcurrentQueueExtensions 6 | { 7 | public static void Clear(this ConcurrentQueue queue) 8 | { 9 | T item; 10 | while (queue.TryDequeue(out item)) { } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Extensions/DateTimeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DotBPE.Baseline.Extensions 4 | { 5 | public static class DateTimeExtensions 6 | { 7 | private const long UnixEpochTicks = 621355968000000000; 8 | private const long UnixEpochSeconds = 62135596800; 9 | private const long UnixEpochMilliseconds = 62135596800000; 10 | 11 | public static DateTimeOffset FromUnixTimeSeconds(this long seconds) 12 | { 13 | long ticks = seconds * TimeSpan.TicksPerSecond + UnixEpochTicks; 14 | return new DateTime(ticks, DateTimeKind.Utc); 15 | } 16 | 17 | public static DateTime FromUnixTimeMilliseconds(this long milliseconds) 18 | { 19 | long ticks = milliseconds * TimeSpan.TicksPerMillisecond + UnixEpochTicks; 20 | return new DateTime(ticks, DateTimeKind.Utc); 21 | } 22 | 23 | public static long ToUnixTimeSeconds(this DateTime dateTime) 24 | { 25 | long seconds = dateTime.ToUniversalTime().Ticks / TimeSpan.TicksPerSecond; 26 | return seconds - UnixEpochSeconds; 27 | } 28 | 29 | public static long ToUnixTimeMilliseconds(this DateTime dateTime) 30 | { 31 | long milliseconds = dateTime.ToUniversalTime().Ticks / TimeSpan.TicksPerMillisecond; 32 | return milliseconds - UnixEpochMilliseconds; 33 | } 34 | 35 | public static string ToNormalString(this DateTime dateTime) 36 | { 37 | return dateTime.ToString("yyyy-MM-dd HH:mm:ss"); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Extensions/ExceptionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace DotBPE.Baseline.Extensions 5 | { 6 | public static class ExceptionExtensions 7 | { 8 | public static Exception GetInnermostException(this Exception exception) 9 | { 10 | if (exception == null) 11 | return null; 12 | 13 | Exception current = exception; 14 | while (current.InnerException != null) 15 | current = current.InnerException; 16 | 17 | return current; 18 | } 19 | 20 | public static string GetMessage(this Exception exception) 21 | { 22 | if (exception == null) 23 | return String.Empty; 24 | 25 | var aggregateException = exception as AggregateException; 26 | if (aggregateException != null) 27 | return String.Join(Environment.NewLine, aggregateException.Flatten().InnerExceptions.Where(ex => !String.IsNullOrEmpty(ex.GetInnermostException().Message)).Select(ex => ex.GetInnermostException().Message)); 28 | 29 | return exception.GetInnermostException().Message; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Extensions/FileExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace DotBPE.Baseline.Extensions 4 | { 5 | public static class FileExtensions 6 | { 7 | public static string GetFileExtension(string fileName) 8 | { 9 | var extension = Path.GetExtension(fileName); 10 | 11 | if (string.IsNullOrEmpty(extension)) 12 | extension = fileName.Substring(fileName.LastIndexOf('.')); 13 | 14 | return extension; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Extensions/NumericExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DotBPE.Baseline.Extensions 4 | { 5 | public static class NumericExtensions 6 | { 7 | 8 | public static TimeSpan Min(this TimeSpan source, TimeSpan other) 9 | { 10 | return source.Ticks > other.Ticks ? other : source; 11 | } 12 | 13 | public static TimeSpan Max(this TimeSpan source, TimeSpan other) 14 | { 15 | return source.Ticks < other.Ticks ? other : source; 16 | } 17 | 18 | public static TimeSpan Seconds(this int secondsValue) 19 | { 20 | return TimeSpan.FromSeconds(secondsValue); 21 | } 22 | public static TimeSpan Milliseconds(this int value) 23 | { 24 | return TimeSpan.FromMilliseconds(value); 25 | } 26 | 27 | public static TimeSpan Minutes(this int value) 28 | { 29 | return TimeSpan.FromMinutes(value); 30 | } 31 | 32 | public static TimeSpan Hours(this int value) 33 | { 34 | return TimeSpan.FromHours(value); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Extensions/TaskExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Runtime.CompilerServices; 3 | using System.Threading.Tasks; 4 | 5 | namespace DotBPE.Baseline.Extensions 6 | { 7 | public static class TaskExtensions 8 | { 9 | [DebuggerStepThrough] 10 | public static ConfiguredTaskAwaitable AnyContext(this Task task) 11 | { 12 | return task.ConfigureAwait(false); 13 | } 14 | 15 | [DebuggerStepThrough] 16 | public static ConfiguredTaskAwaitable AnyContext(this Task task) 17 | { 18 | return task.ConfigureAwait(false); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Utility/IConnectionMapping.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace DotBPE.Baseline.Utility 5 | { 6 | public interface IConnectionMapping 7 | { 8 | Task AddAsync(string key, string connectionId); 9 | 10 | Task> GetConnectionsAsync(string key); 11 | 12 | Task RemoveAsync(string key, string connectionId); 13 | } 14 | 15 | public static class ConnectionMappingExtensions 16 | { 17 | public const string UserIdPrefix = "u-"; 18 | public const string GroupPrefix = "g-"; 19 | 20 | public static Task GroupAddAsync(this IConnectionMapping map, string group, string connectionId) 21 | { 22 | return map.AddAsync(GroupPrefix + group, connectionId); 23 | } 24 | 25 | public static Task GroupRemoveAsync(this IConnectionMapping map, string group, string connectionId) 26 | { 27 | return map.RemoveAsync(GroupPrefix + group, connectionId); 28 | } 29 | 30 | public static Task> GetGroupConnectionsAsync(this IConnectionMapping map, string group) 31 | { 32 | return map.GetConnectionsAsync(GroupPrefix + group); 33 | } 34 | 35 | public static Task UserIdAddAsync(this IConnectionMapping map, string userId, string connectionId) 36 | { 37 | return map.AddAsync(UserIdPrefix + userId, connectionId); 38 | } 39 | 40 | public static Task UserIdRemoveAsync(this IConnectionMapping map, string userId, string connectionId) 41 | { 42 | return map.RemoveAsync(UserIdPrefix + userId, connectionId); 43 | } 44 | 45 | public static Task> GetUserIdConnectionsAsync(this IConnectionMapping map, string userId) 46 | { 47 | return map.GetConnectionsAsync(UserIdPrefix + userId); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/DotBPE.Baseline/Utility/SingletonBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace DotBPE.Baseline.Utility 5 | { 6 | public abstract class SingletonBase where T : class 7 | { 8 | protected SingletonBase() 9 | { 10 | } 11 | 12 | private static readonly Lazy _instance = new Lazy(() => 13 | { 14 | var instance = (T)Activator.CreateInstance(typeof(T), true); 15 | if (instance is IInitializable) 16 | ((IInitializable)instance).Initialize(); 17 | 18 | return instance; 19 | }); 20 | 21 | [DebuggerBrowsable(DebuggerBrowsableState.Never)] 22 | [DebuggerNonUserCode] 23 | public static T Current => _instance.Value; 24 | } 25 | 26 | public interface IInitializable 27 | { 28 | void Initialize(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/DotBPE.BestPractice/AuditLog/AuditLogWriter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.AuditLog; 5 | using Microsoft.Extensions.Logging; 6 | using System.Threading.Tasks; 7 | 8 | namespace DotBPE.BestPractice.AuditLog 9 | { 10 | public class AuditLogWriter : IAuditLogWriter 11 | { 12 | private readonly ILogger _clientLogger; 13 | private readonly ILogger _serverLogger; 14 | public AuditLogWriter(ILoggerFactory loggerFactory) 15 | { 16 | _clientLogger = loggerFactory.CreateLogger("DotBPE.AuditLog.Client"); 17 | _serverLogger = loggerFactory.CreateLogger("DotBPE.AuditLog.Server"); 18 | } 19 | 20 | public Task WriteAsync(string logTxt, AuditLogType auditLogType) 21 | { 22 | var logger = auditLogType == AuditLogType.Client ? _clientLogger : _serverLogger; 23 | logger.LogInformation(logTxt); 24 | 25 | return Task.CompletedTask; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/DotBPE.BestPractice/Constants/ProtocolsConstants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DotBPE.BestPractice 6 | { 7 | public static class ProtocolsConstants 8 | { 9 | public const int RETURN_MESSAGE_NUM = 1; 10 | 11 | public static HashSet FieldMaskList = new HashSet() 12 | { 13 | "password", 14 | "idcard" 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/DotBPE.BestPractice/DotBPE.BestPractice.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | netstandard2.0 7 | $(BestPracticePackageVersion) 8 | Xuanye @ 2017-2019 9 | Xuanye Wong 10 | Xuanye Wong 11 | microservice,dotnet,peach,rpc,dotbpe 12 | icon.png 13 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 14 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 15 | https://github.com/dotbpe/dotbpe 16 | https://raw.githubusercontent.com/dotbpe/dotbpe/master/LICENSE 17 | https://github.com/dotbpe/dotbpe.git 18 | git 19 | 20 | $(BestPracticePackageNotes) 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/DotBPE.BestPractice/Exceptions/BizException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DotBPE.BestPractice 6 | { 7 | 8 | /// 9 | /// 一般业务异常 10 | /// 11 | public class BizException : Exception 12 | { 13 | public BizException() 14 | { 15 | 16 | } 17 | public BizException(int errorCode, string errorMessage) : base(errorMessage) 18 | { 19 | this.ErrorCode = errorCode; 20 | } 21 | 22 | public BizException(string errorMessage) : base(errorMessage) 23 | { 24 | 25 | } 26 | 27 | public BizException(string errorMessage, Exception inner) : base(errorMessage, inner) 28 | { 29 | 30 | } 31 | 32 | 33 | public BizException(int errorCode, string errorMessage, Exception inner) : base(errorMessage, inner) 34 | { 35 | this.ErrorCode = errorCode; 36 | } 37 | 38 | public int ErrorCode { get; } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/DotBPE.BestPractice/HostBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Extra; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.Hosting; 7 | 8 | namespace DotBPE.BestPractice 9 | { 10 | public static class HostBuilderExtensions 11 | { 12 | 13 | /// 14 | /// 组装默认的DotBPE RPC服务端 15 | /// 16 | /// IHostBuilder 实例 17 | /// 服务绑定的端口 18 | /// 是否启用审计日志 19 | /// 20 | public static IHostBuilder UseDefaultRpc(this IHostBuilder @this, int port = 5566, bool auditLog = true) 21 | { 22 | /* 23 | @this.UseRpcServer(port: port) 24 | .UseCastleDynamicProxy() //使用Castle动态代理 25 | .UseProtobufSerializer(true); //消息使用Protobuf序列化RPC通讯,并序列化JSON 26 | 27 | if (auditLog) 28 | { 29 | @this.ConfigureServices(s => 30 | { 31 | s.AddAuditLogService();//审计服务 32 | }); 33 | } 34 | 35 | //加载默认的配置文件 36 | @this.ConfigureAppConfiguration((hostContext, config) => 37 | { 38 | config.AddJsonFile("dotbpe.json", optional: true); 39 | config.AddJsonFile($"dotbpe.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true); 40 | 41 | config.AddJsonFile("serilog.json", optional: true); 42 | config.AddJsonFile($"serilog.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true); 43 | }); 44 | */ 45 | 46 | return @this; 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/DotBPE.BestPractice/TaskResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DotBPE.BestPractice 6 | { 7 | public class TaskResult 8 | { 9 | public static TaskResult Success = new TaskResult(); 10 | public int Code { get; set; } 11 | 12 | public string Message { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/DotBPE.BestPractice/Utility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace DotBPE.BestPractice 5 | { 6 | public static class Utility 7 | { 8 | public static string ClearSQLInject(string input) 9 | { 10 | return !string.IsNullOrEmpty(input) ? input.Replace("--", "").Replace("'", "").Replace(";", ";") : ""; 11 | } 12 | 13 | public static string Base64EnCode(string input) 14 | { 15 | if (string.IsNullOrEmpty(input)) 16 | { 17 | return ""; 18 | } 19 | byte[] b = Encoding.UTF8.GetBytes(input); 20 | return Convert.ToBase64String(b); 21 | } 22 | 23 | public static string Base64Decode(string input) 24 | { 25 | if (string.IsNullOrEmpty(input)) 26 | { 27 | return ""; 28 | } 29 | byte[] b = Convert.FromBase64String(input); 30 | return Encoding.UTF8.GetString(b); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/CallContextServiceActorInterceptor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using DotBPE.Rpc.Server; 6 | using System.Threading.Tasks; 7 | 8 | namespace DotBPE.Extra 9 | { 10 | public class CallContextServiceActorInterceptor : Interceptor 11 | { 12 | 13 | private readonly IContextAccessor _contextAccessor; 14 | 15 | public CallContextServiceActorInterceptor(IContextAccessor contextAccessor) 16 | { 17 | _contextAccessor = contextAccessor; 18 | } 19 | 20 | protected override async Task> ServiceHandle(TRequest req, InvocationContext context, ServiceMethod continuation) 21 | { 22 | if (_contextAccessor != null) 23 | { 24 | if (_contextAccessor.CallContext == null) 25 | { 26 | _contextAccessor.CallContext = new CallContext(); 27 | } 28 | _contextAccessor.CallContext.AddDef(); 29 | } 30 | 31 | try 32 | { 33 | return await base.ServiceHandle(req, context, continuation); 34 | } 35 | finally 36 | { 37 | _contextAccessor?.CallContext.CloseDef(); 38 | } 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/ClientInterceptor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | namespace DotBPE.Extra 5 | { 6 | public abstract class ClientInterceptor : Interceptor 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/DotBPE.Extra.Castle.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | netstandard2.0 6 | DotBPE.Extra 7 | $(ExtraCastlePackageVersion) 8 | Xuanye @ 2017-2019 9 | Xuanye Wong 10 | Xuanye Wong 11 | microservice,dotnet,peach,rpc,dotbpe 12 | icon.png 13 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 14 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 15 | https://github.com/dotbpe/dotbpe 16 | https://raw.githubusercontent.com/dotbpe/dotbpe/master/LICENSE 17 | https://github.com/dotbpe/dotbpe.git 18 | git 19 | 20 | $(ExtraCastlePackageNotes) 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/Extensions/ClientProxyFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Client; 5 | 6 | namespace DotBPE.Extra 7 | { 8 | public static class ClientProxyFactoryExtensions 9 | { 10 | public static IClientProxyFactory UseCastleDynamicClientProxy(this IClientProxyFactory @this) 11 | { 12 | return @this.AddDependencyServices(services => { services.AddDynamicClientProxy(); }); 13 | } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/Extensions/HostBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Microsoft.Extensions.Hosting; 5 | 6 | namespace DotBPE.Extra 7 | { 8 | public static class HostBuilderExtensions 9 | { 10 | public static IHostBuilder UseCastleDynamicProxy(this IHostBuilder @this) 11 | { 12 | return @this.ConfigureServices(services => 13 | { 14 | services.AddDynamicProxy(); 15 | }); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/IRpcServiceInterceptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Castle.DynamicProxy; 3 | 4 | namespace DotBPE.Extra 5 | { 6 | /* 7 | public interface IRpcServiceInterceptor 8 | { 9 | void Before(IInvocation invocation); 10 | 11 | void After(IInvocation invocation); 12 | 13 | void Exception(IInvocation invocation, Exception ex); 14 | } 15 | */ 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/InvocationContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Reflection; 7 | using System.Text; 8 | 9 | namespace DotBPE.Extra 10 | { 11 | public class InvocationContext 12 | { 13 | public Type ServiceType { get; set; } 14 | public MethodInfo Method { get; set; } 15 | public MethodInfo MethodInvocationTarget { get; set; } 16 | 17 | public int Timeout { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/InvokeMeta.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Reflection; 6 | 7 | namespace DotBPE.Extra 8 | { 9 | public class InvokeMeta 10 | { 11 | public int ServiceId { get; set; } 12 | public ushort MessageId { get; set; } 13 | 14 | public string ServiceGroupName { get; set; } 15 | 16 | public MethodInfo InvokeMethod { get; set; } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("DotBPE.Extra.Castle.Tests")] 7 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/ReflectionHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Castle.DynamicProxy; 5 | using DotBPE.Rpc; 6 | using DotBPE.Rpc.Exceptions; 7 | using System; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotBPE.Extra 11 | { 12 | internal class ReflectionHelper 13 | { 14 | public static (Type requestType, Type responseType) GetInvocationCallTypes(IInvocation invocation) 15 | { 16 | var returnType = invocation.Method.ReturnType; 17 | Type responseType; 18 | 19 | if (typeof(Task).IsAssignableFrom(returnType) && returnType.IsGenericType) //Task 20 | { 21 | var innerType = returnType.GetGenericArguments()[0]; 22 | if (typeof(RpcResult).IsAssignableFrom(innerType) && innerType.IsGenericType) 23 | { 24 | responseType = innerType.GetGenericArguments()[0]; 25 | } 26 | else 27 | { 28 | throw new RpcException("Return type must be Task>"); 29 | } 30 | } 31 | else 32 | { 33 | throw new RpcException("Return type must be Task>"); 34 | } 35 | 36 | 37 | return (invocation.Arguments[0].GetType(), responseType); 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/ServiceAuditLogInterceptor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using DotBPE.Rpc.AuditLog; 6 | using DotBPE.Rpc.Protocols; 7 | using DotBPE.Rpc.Server; 8 | using System.Diagnostics; 9 | using System.Threading.Tasks; 10 | 11 | namespace DotBPE.Extra 12 | { 13 | public class ServiceAuditLogInterceptor : Interceptor 14 | { 15 | private readonly IAuditLoggerFactory _auditLoggerFactory; 16 | 17 | public ServiceAuditLogInterceptor(IAuditLoggerFactory auditLoggerFactory = null) 18 | { 19 | _auditLoggerFactory = auditLoggerFactory; 20 | } 21 | 22 | protected override async Task> ServiceHandle(TRequest req, InvocationContext context, ServiceMethod continuation) 23 | { 24 | RpcResult result = null; 25 | var sw = new Stopwatch(); 26 | sw.Start(); 27 | try 28 | { 29 | result = await base.ServiceHandle(req, context, continuation); 30 | } 31 | finally 32 | { 33 | if (result == null) 34 | { 35 | result = new RpcResult() { Code = RpcStatusCodes.CODE_INTERNAL_ERROR }; 36 | } 37 | } 38 | sw.Stop(); 39 | if (_auditLoggerFactory != null) 40 | { 41 | var methodName = $"{context.Method.DeclaringType.Name}.{context.Method.Name}"; 42 | var logger = _auditLoggerFactory.GetLogger(AuditLogType.InProc); 43 | if (logger != null) 44 | { 45 | await logger.Log(methodName, req, result?.Data, result.Code, sw.ElapsedMilliseconds, LocalRpcContext.Instance); 46 | } 47 | } 48 | return result; 49 | } 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Castle/ServiceMethod.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using System.Threading.Tasks; 6 | 7 | namespace DotBPE.Extra 8 | { 9 | /// 10 | /// Server-side handler for unary call. 11 | /// 12 | /// Request message type for this method. 13 | /// Response message type for this method. 14 | public delegate Task> ServiceMethod(TRequest request, InvocationContext callContext) 15 | where TRequest : class 16 | where TResponse : class; 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Json/ClientProxyFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | using DotBPE.Rpc.Client; 2 | 3 | namespace DotBPE.Extra 4 | { 5 | public static class ClientProxyFactoryExtensions 6 | { 7 | public static IClientProxyFactory UseJsonNetSerializer(this IClientProxyFactory @this) 8 | { 9 | return @this.AddDependencyServices(services => { services.AddTextJsonSerializer(); }); 10 | 11 | } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Json/DotBPE.Extra.Json.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | netcoreapp3.1 7 | DotBPE.Extra 8 | $(ExtraJsonPackageVersion) 9 | Xuanye @ 2017-2019 10 | Xuanye Wong 11 | Xuanye Wong 12 | microservice,dotnet,peach,rpc,dotbpe 13 | icon.png 14 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 15 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 16 | https://github.com/dotbpe/dotbpe 17 | https://raw.githubusercontent.com/dotbpe/dotbpe/master/LICENSE 18 | https://github.com/dotbpe/dotbpe.git 19 | git 20 | 21 | $(ExtraJsonPackageNotes) 22 | 23 | Library 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Json/HostBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | 3 | namespace DotBPE.Extra 4 | { 5 | public static class HostBuilderExtensions 6 | { 7 | public static IHostBuilder UseJsonNetSerializer(this IHostBuilder @this) 8 | { 9 | return @this.ConfigureServices(services => services.AddTextJsonSerializer()); 10 | } 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Json/JsonParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using System; 6 | using System.Text; 7 | using System.Text.Json; 8 | using System.Text.Json.Serialization; 9 | 10 | 11 | namespace DotBPE.Extra 12 | { 13 | public class TextJsonParser : IJsonParser 14 | { 15 | private static readonly JsonSerializerOptions JsonSerializerOptions = new JsonSerializerOptions 16 | { 17 | #if NET5_0_OR_GREATER 18 | DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, 19 | #else 20 | IgnoreNullValues = true, 21 | #endif 22 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 23 | WriteIndented = false, 24 | IgnoreReadOnlyProperties = false, 25 | AllowTrailingCommas = false 26 | }; 27 | 28 | public string ToJson(object item) 29 | { 30 | return JsonSerializer.Serialize(item, JsonSerializerOptions); 31 | } 32 | 33 | public string ToJson(T item) where T : class 34 | { 35 | return JsonSerializer.Serialize(item, JsonSerializerOptions); 36 | } 37 | 38 | public object FromJson(string json, Type type) 39 | { 40 | return JsonSerializer.Deserialize(json, type, JsonSerializerOptions); 41 | } 42 | 43 | public T FromJson(string json) where T : class 44 | { 45 | return JsonSerializer.Deserialize(json, JsonSerializerOptions); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Json/JsonSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Text.Json; 4 | using DotBPE.Rpc; 5 | 6 | namespace DotBPE.Extra 7 | { 8 | public class TextJsonSerializer:ISerializer 9 | { 10 | public T Deserialize(byte[] data) 11 | { 12 | if (data == null) 13 | { 14 | return default; 15 | } 16 | var json = Encoding.UTF8.GetString(data); 17 | return JsonSerializer.Deserialize(json); 18 | } 19 | 20 | public byte[] Serialize(T item) 21 | { 22 | if (item == null) 23 | { 24 | return null; 25 | } 26 | return JsonSerializer.SerializeToUtf8Bytes(item); 27 | } 28 | 29 | public object Deserialize(byte[] data, Type type) 30 | { 31 | if (data == null) 32 | { 33 | return null; 34 | } 35 | var json = Encoding.UTF8.GetString(data); 36 | return JsonSerializer.Deserialize(json,type); 37 | } 38 | 39 | public byte[] Serialize(object item) 40 | { 41 | if (item == null) 42 | { 43 | return null; 44 | } 45 | return JsonSerializer.SerializeToUtf8Bytes(item); 46 | } 47 | 48 | public byte CodecType => (byte)Rpc.Codec.CodecType.JSON; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Json/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using DotBPE.Rpc; 3 | 4 | namespace DotBPE.Extra 5 | { 6 | public static class ServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddTextJsonSerializer(this IServiceCollection services) 9 | { 10 | return services 11 | .AddSingleton(); 12 | } 13 | 14 | public static IServiceCollection AddTextJsonParser(this IServiceCollection services) 15 | { 16 | return services 17 | .AddSingleton(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.JsonNet/ClientProxyFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | using DotBPE.Rpc.Client; 2 | 3 | namespace DotBPE.Extra 4 | { 5 | public static class ClientProxyFactoryExtensions 6 | { 7 | public static IClientProxyFactory UseJsonNetSerializer(this IClientProxyFactory @this) 8 | { 9 | return @this.AddDependencyServices(services => { services.AddJsonNetSerializer(); }); 10 | 11 | } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.JsonNet/DotBPE.Extra.JsonNet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | netstandard2.0 7 | DotBPE.Extra 8 | $(ExtraJsonNetPackageVersion) 9 | Xuanye @ 2017-2019 10 | Xuanye Wong 11 | Xuanye Wong 12 | microservice,dotnet,peach,rpc,dotbpe 13 | icon.png 14 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 15 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 16 | https://github.com/dotbpe/dotbpe 17 | https://raw.githubusercontent.com/dotbpe/dotbpe/master/LICENSE 18 | https://github.com/dotbpe/dotbpe.git 19 | git 20 | 21 | $(ExtraJsonNetPackageNotes) 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.JsonNet/HostBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | 3 | namespace DotBPE.Extra 4 | { 5 | public static class HostBuilderExtensions 6 | { 7 | public static IHostBuilder UseJsonNetSerializer(this IHostBuilder @this) 8 | { 9 | return @this.ConfigureServices(services => services.AddJsonNetSerializer()); 10 | } 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.JsonNet/JsonParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using DotBPE.Rpc; 4 | using Newtonsoft.Json; 5 | 6 | namespace DotBPE.Extra 7 | { 8 | public class JsonParser:IJsonParser 9 | { 10 | static readonly JsonSerializerSettings settings = new JsonSerializerSettings 11 | { 12 | DefaultValueHandling = DefaultValueHandling.Ignore 13 | }; 14 | public string ToJson(object item) 15 | { 16 | return JsonConvert.SerializeObject(item,Formatting.None,settings); 17 | } 18 | 19 | public string ToJson(T item) where T : class 20 | { 21 | return JsonConvert.SerializeObject(item,Formatting.None,settings); 22 | } 23 | 24 | public object FromJson(string json, Type type) 25 | { 26 | return JsonConvert.DeserializeObject(json, type,settings); 27 | } 28 | 29 | public T FromJson(string json) where T : class 30 | { 31 | return JsonConvert.DeserializeObject(json,settings); 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.JsonNet/JsonSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using DotBPE.Rpc; 4 | using Newtonsoft.Json; 5 | 6 | namespace DotBPE.Extra 7 | { 8 | public class JsonSerializer:ISerializer 9 | { 10 | public T Deserialize(byte[] data) 11 | { 12 | if (data == null) 13 | { 14 | return default(T); 15 | } 16 | var json = Encoding.UTF8.GetString(data); 17 | return JsonConvert.DeserializeObject(json); 18 | } 19 | 20 | public byte[] Serialize(T item) 21 | { 22 | if (item == null) 23 | { 24 | return null; 25 | } 26 | var json = JsonConvert.SerializeObject(item); 27 | return Encoding.UTF8.GetBytes(json); 28 | } 29 | 30 | public object Deserialize(byte[] data, Type type) 31 | { 32 | if (data == null) 33 | { 34 | return null; 35 | } 36 | var json = Encoding.UTF8.GetString(data); 37 | return JsonConvert.DeserializeObject(json, type); 38 | } 39 | 40 | public byte[] Serialize(object item) 41 | { 42 | if (item == null) 43 | { 44 | return null; 45 | } 46 | var json = JsonConvert.SerializeObject(item); 47 | return Encoding.UTF8.GetBytes(json); 48 | } 49 | 50 | public byte CodecType => (byte)Rpc.Codec.CodecType.JSON; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.JsonNet/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using DotBPE.Rpc; 3 | 4 | namespace DotBPE.Extra 5 | { 6 | public static class ServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddJsonNetSerializer(this IServiceCollection services) 9 | { 10 | return services 11 | .AddSingleton(); 12 | } 13 | 14 | public static IServiceCollection AddJsonNetParser(this IServiceCollection services) 15 | { 16 | return services 17 | .AddSingleton(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.MessagePack/ClientProxyFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | using DotBPE.Rpc.Client; 2 | 3 | namespace DotBPE.Extra 4 | { 5 | public static class ClientProxyFactoryExtensions 6 | { 7 | public static IClientProxyFactory UseMessagePackSerializer(this IClientProxyFactory @this) 8 | { 9 | return @this.AddDependencyServices(services => { services.AddMessagePackSerializer(); }); 10 | 11 | } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.MessagePack/DotBPE.Extra.MessagePack.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | netstandard2.0 6 | DotBPE.Extra 7 | $(ExtraMessagePackPackageVersion) 8 | Xuanye @ 2017-2019 9 | Xuanye Wong 10 | Xuanye Wong 11 | microservice,dotnet,peach,rpc,dotbpe 12 | icon.png 13 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 14 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 15 | https://github.com/dotbpe/dotbpe 16 | https://raw.githubusercontent.com/dotbpe/dotbpe/master/LICENSE 17 | https://github.com/dotbpe/dotbpe.git 18 | git 19 | 20 | $(ExtraMessagePackPackageNotes) 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.MessagePack/HostBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | 3 | namespace DotBPE.Extra 4 | { 5 | public static class HostBuilderExtensions 6 | { 7 | public static IHostBuilder UseMessagePackSerializer(this IHostBuilder @this) 8 | { 9 | return @this.ConfigureServices(services => services.AddMessagePackSerializer()); 10 | } 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.MessagePack/MessagePackSerializer.cs: -------------------------------------------------------------------------------- 1 | using DotBPE.Rpc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using MessagePack; 6 | 7 | namespace DotBPE.Extra 8 | { 9 | public class MessagePackSerializer : ISerializer 10 | { 11 | public T Deserialize(byte[] bytes) 12 | { 13 | return MessagePack.MessagePackSerializer.Deserialize(bytes); 14 | } 15 | 16 | public object Deserialize(byte[] data, Type type) 17 | { 18 | return MessagePack.MessagePackSerializer.Deserialize(type, data); 19 | } 20 | 21 | public byte[] Serialize(T item) 22 | { 23 | return MessagePack.MessagePackSerializer.Serialize(item); 24 | } 25 | 26 | public byte[] Serialize(object item) 27 | { 28 | return MessagePack.MessagePackSerializer.Serialize(item.GetType(),item); 29 | } 30 | 31 | public byte CodecType => (byte)Rpc.Codec.CodecType.MessagePack; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.MessagePack/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using DotBPE.Rpc; 3 | 4 | namespace DotBPE.Extra 5 | { 6 | public static class ServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddMessagePackSerializer(this IServiceCollection services) 9 | { 10 | return services 11 | .AddSingleton(); 12 | 13 | 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Protobuf/ClientProxyFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | using DotBPE.Rpc.Client; 2 | 3 | namespace DotBPE.Extra 4 | { 5 | public static class ClientProxyFactoryExtensions 6 | { 7 | public static IClientProxyFactory UseProtobufSerializer(this IClientProxyFactory @this) 8 | { 9 | return @this.AddDependencyServices(services => { services.AddProtobufSerializer(); }); 10 | 11 | } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Protobuf/DotBPE.Extra.Protobuf.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | netstandard2.0 7 | DotBPE.Extra 8 | $(ExtraProtobufPackageVersion) 9 | Xuanye @ 2017-2019 10 | Xuanye Wong 11 | Xuanye Wong 12 | microservice,dotnet,peach,rpc,dotbpe 13 | icon.png 14 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 15 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 16 | https://github.com/dotbpe/dotbpe 17 | https://raw.githubusercontent.com/dotbpe/dotbpe/master/LICENSE 18 | https://github.com/dotbpe/dotbpe.git 19 | git 20 | 21 | $(ExtraProtobufPackageNotes) 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Protobuf/HostBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | 3 | namespace DotBPE.Extra 4 | { 5 | public static class HostBuilderExtensions 6 | { 7 | public static IHostBuilder UseProtobufSerializer(this IHostBuilder @this, bool useJsonParser = false) 8 | { 9 | return @this.ConfigureServices(services => 10 | { 11 | if (useJsonParser) 12 | { 13 | services.AddProtobufSerializerAndJsonParser(); 14 | } 15 | else 16 | { 17 | services.AddProtobufSerializer(); 18 | } 19 | }); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/DotBPE.Extra.Protobuf/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using DotBPE.Rpc; 3 | using Microsoft.Extensions.DependencyInjection.Extensions; 4 | 5 | namespace DotBPE.Extra 6 | { 7 | public static class ServiceCollectionExtensions 8 | { 9 | public static IServiceCollection AddProtobufSerializer(this IServiceCollection services) 10 | { 11 | return services 12 | .AddSingleton(); 13 | 14 | } 15 | 16 | public static IServiceCollection AddProtobufSerializerAndJsonParser(this IServiceCollection services) 17 | { 18 | services.TryAddSingleton(); 19 | return services 20 | .AddSingleton(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Attributes/HttpRouteAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | 6 | namespace DotBPE.Gateway 7 | { 8 | [AttributeUsage(AttributeTargets.Method)] 9 | public class HttpRouteAttribute : Attribute 10 | { 11 | 12 | public HttpRouteAttribute(string path, HttpVerb acceptVerb = HttpVerb.Any, string version = "1.0.0") 13 | { 14 | 15 | Path = path; 16 | AcceptVerb = acceptVerb; 17 | Version = version; 18 | } 19 | 20 | 21 | public string Category { get; set; } = "default"; 22 | public string Path { get; } 23 | 24 | public string Version { get; } = "1.0.0"; 25 | 26 | public HttpVerb AcceptVerb { get; } 27 | 28 | public string PluginName { get; set; } 29 | 30 | 31 | private Type _pluginType; 32 | public Type PluginType 33 | { 34 | get 35 | { 36 | if (!string.IsNullOrEmpty(PluginName)) 37 | { 38 | if (_pluginType != null) 39 | { 40 | return _pluginType; 41 | } 42 | _pluginType = Type.GetType(PluginName); 43 | return _pluginType; 44 | } 45 | 46 | return null; 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Contracts/IHttpApiErrorProcess.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using System.Net; 6 | using System.Runtime.Serialization; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotBPE.Gateway 11 | { 12 | public interface IHttpApiErrorProcess 13 | { 14 | Task ProcessAsync(HttpResponse response, Encoding encoding, Error e); 15 | } 16 | 17 | [DataContract] 18 | public class Error 19 | { 20 | [DataMember(Order = 1, Name = "code")] 21 | public int Code { get; set; } 22 | 23 | [DataMember(Order = 1, Name = "message")] 24 | public string Message { get; set; } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Contracts/IHttpApiOutputProcess.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using Microsoft.AspNetCore.Http; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Gateway 10 | { 11 | public interface IHttpApiOutputProcess 12 | { 13 | Task ProcessAsync(HttpRequest request, HttpResponse response, Encoding encoding, RpcResult result); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Contracts/IHttpOutputProcessPlugin.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using Microsoft.AspNetCore.Http; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Gateway 10 | { 11 | public interface IHttpOutputProcessPlugin : IHttpPlugin 12 | { 13 | Task ProcessAsync(HttpRequest request, HttpResponse response, Encoding encoding, RpcResult result); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Contracts/IHttpPlugin.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | namespace DotBPE.Gateway 5 | { 6 | public interface IHttpPlugin 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Contracts/IHttpProcessPlugin.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using System.Threading.Tasks; 6 | 7 | namespace DotBPE.Gateway 8 | { 9 | public interface IHttpProcessPlugin : IHttpPlugin 10 | { 11 | Task ProcessAsync(HttpRequest req, HttpResponse res); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Contracts/IHttpRequestParsePlugin.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using System.Net; 6 | using System.Threading.Tasks; 7 | 8 | namespace DotBPE.Gateway 9 | { 10 | public interface IHttpRequestParsePlugin : IHttpPlugin 11 | { 12 | Task<(object, int, string)> ParseAsync(HttpRequest request); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Contracts/IHttpRequestParsePostPlugin.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using System.Net; 6 | using System.Threading.Tasks; 7 | 8 | namespace DotBPE.Gateway 9 | { 10 | public interface IHttpRequestParsePostPlugin : IHttpPlugin 11 | { 12 | Task<(int statusCode, string errorMessage)> ParseAsync(HttpRequest request, object requestMessage); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/DotBPE.Gateway.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | netcoreapp3.1;net6.0;net7.0 7 | $(GatewayPackageVersion) 8 | Xuanye @ 2017-2019 9 | Xuanye Wong 10 | Xuanye Wong 11 | microservice,dotnet,peach,rpc,dotbpe 12 | icon.png 13 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 14 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 15 | https://github.com/dotbpe/dotbpe 16 | https://raw.githubusercontent.com/dotbpe/dotbpe/master/LICENSE 17 | https://github.com/dotbpe/dotbpe.git 18 | git 19 | 20 | $(GatewayPackageNotes) 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Extensions/HttpRequestExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Linq; 5 | 6 | 7 | namespace Microsoft.AspNetCore.Http 8 | { 9 | public static class HttpRequestExtensions 10 | { 11 | public static string GetClientIp(this HttpRequest request) 12 | { 13 | var ip = request.Headers["X-Forwarded-For"].FirstOrDefault(); 14 | 15 | if (string.IsNullOrEmpty(ip)) 16 | { 17 | ip = request.Headers["X-Real-IP"].FirstOrDefault(); 18 | } 19 | 20 | if (string.IsNullOrEmpty(ip)) 21 | { 22 | var IPAddress = request.HttpContext.Connection.RemoteIpAddress; 23 | 24 | ip = IPAddress.IsIPv4MappedToIPv6 ? IPAddress.MapToIPv4().ToString() : IPAddress.ToString(); 25 | } 26 | return ip; 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/HttpApiOption.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | 6 | namespace DotBPE.Gateway 7 | { 8 | public class HttpApiOptions 9 | { 10 | 11 | public string Category { get; set; } = "default"; 12 | public string Pattern { get; set; } 13 | 14 | public string Version { get; set; } = "1.0.0"; 15 | 16 | public HttpVerb AcceptVerb { get; set; } 17 | 18 | public string PluginName { get; set; } 19 | 20 | 21 | private Type _pluginType; 22 | public Type PluginType 23 | { 24 | get 25 | { 26 | if (!string.IsNullOrEmpty(PluginName)) 27 | { 28 | if (_pluginType != null) 29 | { 30 | return _pluginType; 31 | } 32 | _pluginType = Type.GetType(PluginName); 33 | return _pluginType; 34 | } 35 | 36 | return null; 37 | } 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/HttpVerb.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | 6 | namespace DotBPE.Gateway 7 | { 8 | [Flags] 9 | public enum HttpVerb 10 | { 11 | UnKnown = 0, 12 | Get = 1, 13 | Post = 2, 14 | Put = 4, 15 | Delete = 8, 16 | Patch = 16, 17 | Any = 31 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Internal/ApiEndpointConventionBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Microsoft.AspNetCore.Builder; 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace DotBPE.Gateway.Internal 9 | { 10 | internal class ApiEndpointConventionBuilder : IEndpointConventionBuilder 11 | { 12 | private readonly IEnumerable _endpointConventionBuilders; 13 | 14 | public ApiEndpointConventionBuilder(IEnumerable endpointConventionBuilders) 15 | { 16 | _endpointConventionBuilders = endpointConventionBuilders; 17 | } 18 | 19 | public void Add(Action convention) 20 | { 21 | foreach (var endpointConventionBuilder in _endpointConventionBuilders) 22 | { 23 | endpointConventionBuilder.Add(convention); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Internal/ApiMethod.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Reflection; 8 | using System.Text; 9 | 10 | namespace DotBPE.Gateway.Internal 11 | { 12 | 13 | public interface IApiMethod 14 | { 15 | string ServiceName { get; } 16 | string Name { get; } 17 | string FullName { get; } 18 | } 19 | 20 | internal class ApiMethod : IApiMethod 21 | where TRequest : class 22 | where TResponse : class 23 | { 24 | public ApiMethod(string serviceName, MethodInfo handler) 25 | { 26 | ServiceName = serviceName; 27 | HandlerMethod = handler; 28 | Name = handler.Name; 29 | FullName = GetFullName(serviceName, Name); 30 | } 31 | 32 | public string ServiceName { get; private set; } 33 | public string Name { get; private set; } 34 | public string FullName { get; private set; } 35 | public MethodInfo HandlerMethod { get; private set; } 36 | 37 | private static string GetFullName(string serviceName, string methodName) 38 | { 39 | return $"{serviceName}.{methodName}"; 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Internal/ApiMethodInvoker.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using DotBPE.Rpc.Client; 6 | using DotBPE.Rpc.Server; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Gateway.Internal 10 | { 11 | internal class ApiMethodInvoker 12 | where TRequest : class 13 | where TResponse : class 14 | where TService : class 15 | { 16 | private readonly ServiceMethod _invoker; 17 | private readonly ServiceMethodWithTimeout _invokerWithTimeout; 18 | private readonly int _timeout; 19 | private readonly IClientProxy _clientProxy; 20 | 21 | public ApiMethodInvoker( 22 | ServiceMethod invoker, 23 | ServiceMethodWithTimeout invokerWithTimeout, 24 | int timeout, 25 | IClientProxy clientProxy 26 | ) 27 | { 28 | _invoker = invoker; 29 | _invokerWithTimeout = invokerWithTimeout; 30 | _timeout = timeout; 31 | _clientProxy = clientProxy; 32 | } 33 | 34 | 35 | public async Task> Invoke(TRequest request) 36 | { 37 | var instance = _clientProxy.Create(); 38 | if (_invoker != null) 39 | { 40 | return await _invoker(instance, request); 41 | } 42 | else 43 | { 44 | return await _invokerWithTimeout(instance, request, _timeout); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Internal/ApiMethodModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Routing.Patterns; 6 | using System.Collections.Generic; 7 | 8 | namespace DotBPE.Gateway.Internal 9 | { 10 | internal class ApiMethodModel 11 | { 12 | public ApiMethodModel(IApiMethod method, RoutePattern pattern, IList metadata, RequestDelegate requestDelegate) 13 | { 14 | Method = method; 15 | Pattern = pattern; 16 | Metadata = metadata; 17 | RequestDelegate = requestDelegate; 18 | } 19 | 20 | public IApiMethod Method { get; } 21 | public RoutePattern Pattern { get; } 22 | public IList Metadata { get; } 23 | public RequestDelegate RequestDelegate { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Internal/ApiMethodProviderContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | 5 | using DotBPE.Rpc.Server; 6 | using Microsoft.AspNetCore.Routing.Patterns; 7 | using System.Collections.Generic; 8 | using RequestDelegate = Microsoft.AspNetCore.Http.RequestDelegate; 9 | 10 | namespace DotBPE.Gateway.Internal 11 | { 12 | public class ApiMethodProviderContext where TService : class 13 | { 14 | public ApiMethodProviderContext() 15 | { 16 | Methods = new List(); 17 | } 18 | 19 | internal List Methods { get; } 20 | 21 | 22 | 23 | internal void AddMethod(ApiMethod method, RoutePattern pattern, IList metadata, RequestDelegate invoker) 24 | where TRequest : class 25 | where TResponse : class 26 | { 27 | var methodModel = new ApiMethodModel(method, pattern, metadata, invoker); 28 | Methods.Add(methodModel); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Internal/DefaultApiMethodProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using DotBPE.Rpc.Client; 6 | using Microsoft.Extensions.Logging; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | 11 | namespace DotBPE.Gateway.Internal 12 | { 13 | internal class DefaultApiMethodProvider : IApiMethodProvider 14 | where TService : class 15 | { 16 | private readonly RpcGatewayOption _gatewayOption; 17 | private readonly IClientProxy _clientProxy; 18 | private readonly IJsonParser _jsonParser; 19 | private readonly ILoggerFactory _loggerFactory; 20 | 21 | public DefaultApiMethodProvider( 22 | RpcGatewayOption gatewayOption 23 | , IClientProxy clientProxy 24 | , IJsonParser jsonParser 25 | , ILoggerFactory loggerFactory 26 | ) 27 | { 28 | _gatewayOption = gatewayOption; 29 | _clientProxy = clientProxy; 30 | _jsonParser = jsonParser; 31 | _loggerFactory = loggerFactory; 32 | 33 | } 34 | 35 | 36 | public void OnMethodDiscovery(ApiMethodProviderContext context) 37 | { 38 | try 39 | { 40 | var binder = new ApiProviderServiceBinder(context, _gatewayOption, _clientProxy, _jsonParser, _loggerFactory); 41 | binder.Bind(); 42 | } 43 | catch (Exception ex) 44 | { 45 | throw new InvalidOperationException($"Error binding RPC service To HttpApi '{typeof(TService).Name}'.", ex); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Internal/HttpApiMetadata.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Reflection; 7 | using System.Text; 8 | 9 | namespace DotBPE.Gateway.Internal 10 | { 11 | internal class HttpApiMetadata 12 | { 13 | public HttpApiMetadata(MethodInfo handerMethod, HttpApiOptions httpApiOptions, Type inputType, Type outputType) 14 | { 15 | HanderMethod = handerMethod; 16 | HttpApiOptions = httpApiOptions; 17 | InputType = inputType; 18 | OutputType = outputType; 19 | } 20 | 21 | public Type HanderServiceType => HanderMethod?.DeclaringType; 22 | 23 | public Type InputType { get; } 24 | public Type OutputType { get; } 25 | 26 | public MethodInfo HanderMethod { get; } 27 | public HttpApiOptions HttpApiOptions { get; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Internal/IApiMethodProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Server; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace DotBPE.Gateway.Internal 10 | { 11 | public interface IApiMethodProvider where TService : class 12 | { 13 | void OnMethodDiscovery(ApiMethodProviderContext context); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("DotBPE.Gateway.Tests")] 7 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/RpcGatewayOption.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | namespace DotBPE.Gateway 5 | { 6 | public class RpcGatewayOption 7 | { 8 | public static RpcGatewayOption Default = new RpcGatewayOption(); 9 | public string CodeFieldName { get; set; } = "code"; 10 | public string MessageFieldName { get; set; } = "message"; 11 | public string DataFieldName { get; set; } = "data"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/ISwaggerProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DotBPE.Gateway.Swagger 6 | { 7 | public interface ISwaggerProvider 8 | { 9 | SwaggerInfo GetSwaggerInfo(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/Models/SwaggerApiContactInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace DotBPE.Gateway.Swagger 4 | { 5 | [DataContract] 6 | public class SwaggerApiContactInfo 7 | { 8 | [DataMember(Name = "name")] 9 | public string Name { get; set; } 10 | [DataMember(Name = "url")] 11 | public string Url { get; set; } 12 | [DataMember(Name = "email")] 13 | public string Email { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/Models/SwaggerApiInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace DotBPE.Gateway.Swagger 4 | { 5 | 6 | [DataContract] 7 | public class SwaggerApiInfo 8 | { 9 | [DataMember(Name = "version")] 10 | public string Version { get; set; } = "1.0.0"; 11 | [DataMember(Name = "title")] 12 | public string Title { get; set; } = "Api Document"; 13 | [DataMember(Name = "description")] 14 | public string Description { get; set; } = "Api Document"; 15 | 16 | [DataMember(Name = "contact")] 17 | public SwaggerApiContactInfo Contact { get; set; } 18 | 19 | [DataMember(Name = "termsOfService")] 20 | public string TermsOfService { get; set; } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/Models/SwaggerApiParameters.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace DotBPE.Gateway.Swagger 4 | { 5 | [DataContract] 6 | public class SwaggerApiParameters 7 | { 8 | [DataMember(Name = "in")] 9 | public string In { get; set; } = "query";//body formData 10 | [DataMember(Name = "name")] 11 | public string Name { get; set; } 12 | [DataMember(Name = "type")] 13 | public string Type { get; set; } 14 | [DataMember(Name = "description")] 15 | public string Description { get; set; } 16 | 17 | [DataMember(Name = "required")] 18 | public bool Required { get; set; } 19 | 20 | [DataMember(Name = "defaultValue")] 21 | public string DefaultValue { get; set; } 22 | 23 | [DataMember(Name = "format")] 24 | public string Format { get; set; } 25 | 26 | 27 | [DataMember(Name = "schema")] 28 | public SwaggerItemSchema Schema { get; set; } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/Models/SwaggerApiResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace DotBPE.Gateway.Swagger 4 | { 5 | 6 | [DataContract] 7 | public class SwaggerApiResponse 8 | { 9 | [DataMember(Name = "description")] 10 | public string Description { get; set; } 11 | 12 | [DataMember(Name = "schema")] 13 | public SwaggerItemSchema Schema { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/Models/SwaggerDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.Serialization; 3 | 4 | namespace DotBPE.Gateway.Swagger 5 | { 6 | [DataContract] 7 | public class SwaggerDefinition 8 | { 9 | [DataMember(Name = "type")] 10 | public string Type { get; set; } 11 | 12 | [DataMember(Name = "properties")] 13 | public Dictionary Properties { get; set; } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/Models/SwaggerInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.Serialization; 3 | 4 | namespace DotBPE.Gateway.Swagger 5 | { 6 | [DataContract] 7 | public class SwaggerInfo 8 | { 9 | [DataMember(Name = "swagger")] 10 | public string Swagger { get; set; } = "2.0"; 11 | 12 | [DataMember(Name = "info")] 13 | public SwaggerApiInfo Info { get; set; } 14 | 15 | [DataMember(Name = "schemes")] 16 | public string[] Schemes { get; set; } = {"http"}; 17 | 18 | [DataMember(Name = "tags")] 19 | public List Tags { get; set; } 20 | 21 | [DataMember(Name = "host")] 22 | public string Host { get; set; } 23 | 24 | [DataMember(Name = "basePath")] 25 | public string BasePath { get; set; } 26 | 27 | [DataMember(Name = "paths")] 28 | public Dictionary> Paths { get; set; } 29 | 30 | 31 | [DataMember(Name = "definitions")] 32 | public Dictionary Definitions { get; set; } 33 | 34 | 35 | } 36 | 37 | 38 | [DataContract] 39 | public class SwaggerTag 40 | { 41 | [DataMember(Name = "name")] 42 | public string Name { get; set; } 43 | 44 | [DataMember(Name = "description")] 45 | public string Description { get; set; } 46 | } 47 | 48 | 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/Models/SwaggerItemSchema.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.Serialization; 3 | 4 | namespace DotBPE.Gateway.Swagger 5 | { 6 | 7 | [DataContract] 8 | public class SwaggerItemSchema 9 | { 10 | 11 | } 12 | 13 | [DataContract] 14 | public class SwaggerSingleItemSchema:SwaggerItemSchema 15 | { 16 | //$ref 17 | [DataMember(Name = "$ref")] 18 | public string Ref { get; set; } 19 | } 20 | [DataContract] 21 | public class SwaggerArrayItemSchema:SwaggerItemSchema 22 | { 23 | [DataMember(Name = "$ref")] 24 | public string Type { get; } = "array"; 25 | 26 | [DataMember(Name = "items")] 27 | public List Items { get; set; } = new List(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/Models/SwaggerMethod.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.Serialization; 3 | 4 | namespace DotBPE.Gateway.Swagger 5 | { 6 | [DataContract] 7 | public class SwaggerMethod 8 | { 9 | [DataMember(Name = "tags")] 10 | public List Tags { get; set; } 11 | 12 | [DataMember(Name = "summary")] 13 | public string Summary { get; set; } 14 | 15 | [DataMember(Name = "description")] 16 | public string Description { get; set; } 17 | 18 | 19 | [DataMember(Name = "operationId")] 20 | public string OperationId { get; set; } 21 | 22 | [DataMember(Name = "consumes")] 23 | public List Consumes { get; } = new List(); 24 | 25 | [DataMember(Name = "produces")] 26 | public List Produces { get; } = new List(); 27 | 28 | 29 | [DataMember(Name = "parameters")] 30 | public List Parameters { get; } = new List(); 31 | 32 | [DataMember(Name = "responses")] 33 | public Dictionary Responses { get; } = new Dictionary(); 34 | 35 | 36 | [DataMember(Name = "version")] 37 | public string Version { get; set; } 38 | 39 | } 40 | 41 | 42 | [DataContract] 43 | public class SwaggerGetMethod:SwaggerMethod 44 | { 45 | 46 | 47 | } 48 | 49 | [DataContract] 50 | public class SwaggerPostMethod:SwaggerMethod 51 | { 52 | 53 | } 54 | [DataContract] 55 | public class SwaggerPutMethod:SwaggerMethod 56 | { 57 | 58 | 59 | } 60 | [DataContract] 61 | public class SwaggerDeleteMethod:SwaggerMethod 62 | { 63 | 64 | 65 | } 66 | [DataContract] 67 | public class SwaggerPatchMethod:SwaggerMethod 68 | { 69 | 70 | 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/Models/SwaggerPropertyDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace DotBPE.Gateway.Swagger 4 | { 5 | [DataContract] 6 | public class SwaggerPropertyDefinition 7 | { 8 | [DataMember(Name = "type")] 9 | public string Type { get; set; } 10 | 11 | [DataMember(Name = "format")] 12 | public string Format { get; set; } 13 | 14 | [DataMember(Name = "$ref")] 15 | public string Ref{get; set; } 16 | 17 | [DataMember(Name = "example")] 18 | public string Example { get; set; } 19 | 20 | [DataMember(Name = "items")] 21 | public SwaggerItemSchema Items { get; set; } 22 | 23 | [DataMember(Name = "description")] 24 | public string Description { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/SwaggerOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DotBPE.Gateway.Swagger 6 | { 7 | public class SwaggerOptions 8 | { 9 | public SwaggerApiInfo ApiInfo { get; set; } 10 | 11 | 12 | public string Host { get; set; } 13 | public string BasePath { get; set; } = "/"; 14 | 15 | 16 | public List IngoreFields { get; } = new List { 17 | "Identity", 18 | "ClientIp", 19 | "XRequestId", 20 | "Header", 21 | "AcceptLanguage", 22 | "XClientVersion", 23 | "XDeviceId", 24 | "XDeviceName", 25 | "XDeviceOs", 26 | "XSourceType", 27 | "XClientVersion" 28 | }; 29 | 30 | public string RoutePath { get; set; } = "/v2/swagger.json"; 31 | 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/SwaggerUIOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Gateway.Swagger 10 | { 11 | public class SwaggerUIOptions 12 | { 13 | public string SwaggerJsonPath { get; set; } = "/v2/swagger.json"; 14 | /// 15 | /// Gets or sets a route prefix for accessing the swagger-ui 16 | /// 17 | public string RoutePrefix { get; set; } = "/swagger"; 18 | 19 | /// 20 | /// Gets or sets a Stream function for retrieving the swagger-ui page 21 | /// 22 | public Func IndexStream { get; set; } = () => typeof(SwaggerUIOptions).GetTypeInfo().Assembly 23 | .GetManifestResourceStream($"{typeof(SwaggerUIOptions).GetTypeInfo().Assembly.GetName().Name}.Swagger.UI.index.html"); 24 | 25 | /// 26 | /// Gets or sets a title for the swagger-ui page 27 | /// 28 | public string DocumentTitle { get; set; } = "Rpc Swagger Api"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/UI/favicon.7cc1a2af.svg: -------------------------------------------------------------------------------- 1 | 2 | Download more icon variants from https://tabler-icons.io/i/api-app 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/DotBPE.Gateway/Swagger/UI/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Vite App 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Attributes/RpcMethodAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc 9 | { 10 | [AttributeUsage(AttributeTargets.Method)] 11 | public class RpcMethodAttribute : Attribute 12 | { 13 | public RpcMethodAttribute() 14 | { 15 | 16 | } 17 | public RpcMethodAttribute(ushort messageId) 18 | { 19 | MessageId = messageId; 20 | } 21 | 22 | public ushort MessageId { get; set; } 23 | 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Attributes/RpcServiceAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc 9 | { 10 | [AttributeUsage(AttributeTargets.Interface)] 11 | public class RpcServiceAttribute : Attribute 12 | { 13 | public RpcServiceAttribute() 14 | { 15 | 16 | } 17 | public RpcServiceAttribute(int serviceId, string groupName = "default") 18 | { 19 | ServiceId = serviceId; 20 | GroupName = groupName; 21 | } 22 | 23 | public int ServiceId { get; set; } 24 | 25 | public string GroupName { get; set; } = "default"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/AuditLog/AuditLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Threading.Tasks; 5 | 6 | namespace DotBPE.Rpc.AuditLog 7 | { 8 | public class AuditLogger : IAuditLogger 9 | { 10 | private readonly IAuditLogWriter _writer; 11 | private readonly IAuditLogFormatter _formatter; 12 | 13 | public AuditLogger(AuditLogType auditLogType, IAuditLogWriter writer, IAuditLogFormatter formatter) 14 | { 15 | AuditLogType = auditLogType; 16 | _writer = writer; 17 | _formatter = formatter; 18 | } 19 | 20 | public AuditLogType AuditLogType { get; } 21 | 22 | public Task Log(string methodName, object req, object res, int statusCode, long elapsedMS, IRpcContext context) 23 | { 24 | try 25 | { 26 | var logInfo = new AuditLogInfo() 27 | { 28 | MethodName = methodName, 29 | Request = req, 30 | Response = res, 31 | Context = context, 32 | AuditLogType = AuditLogType, 33 | StatusCode = statusCode, 34 | ElapsedMS = elapsedMS, 35 | }; 36 | var logText = _formatter.Format(logInfo); 37 | 38 | return _writer.WriteAsync(logText, AuditLogType); 39 | } 40 | catch 41 | { 42 | //do nothing here 43 | } 44 | return Task.CompletedTask; 45 | 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/AuditLog/IAuditLogFormatter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc.AuditLog 9 | { 10 | public interface IAuditLogFormatter 11 | { 12 | string Format(IAuditLogInfo auditLog); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/AuditLog/IAuditLogInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Reflection; 5 | 6 | namespace DotBPE.Rpc.AuditLog 7 | { 8 | 9 | public class AuditLogInfo : IAuditLogInfo 10 | { 11 | public string MethodName { get; set; } 12 | 13 | public IRpcContext Context { get; set; } 14 | 15 | public object Request { get; set; } 16 | public object Response { get; set; } 17 | public int StatusCode { get; set; } 18 | public long ElapsedMS { get; set; } 19 | public AuditLogType AuditLogType { get; set; } 20 | } 21 | 22 | public interface IAuditLogInfo 23 | { 24 | string MethodName { get; } 25 | IRpcContext Context { get; } 26 | object Request { get; } 27 | object Response { get; } 28 | int StatusCode { get; } 29 | long ElapsedMS { get; } 30 | AuditLogType AuditLogType { get; } 31 | } 32 | 33 | public enum AuditLogType 34 | { 35 | Client, 36 | Service, 37 | InProc 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/AuditLog/IAuditLogWriter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Rpc.AuditLog 10 | { 11 | public interface IAuditLogWriter 12 | { 13 | Task WriteAsync(string log, AuditLogType auditLogType); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/AuditLog/IAuditLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Rpc.AuditLog 10 | { 11 | public interface IAuditLogger 12 | { 13 | AuditLogType AuditLogType { get; } 14 | Task Log(string methodName, object req, object res, int statusCode, long elapsedMS, IRpcContext context); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/AuditLog/IAuditLoggerFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Rpc.AuditLog 10 | { 11 | public interface IAuditLoggerFactory 12 | { 13 | IAuditLogger GetLogger(AuditLogType auditLogType); 14 | } 15 | 16 | public class AuditLoggerFactory : IAuditLoggerFactory 17 | { 18 | private readonly IAuditLogger _clientLogger; 19 | private readonly IAuditLogger _serviceLogger; 20 | public AuditLoggerFactory(IAuditLogWriter writer, IAuditLogFormatter formatter) 21 | { 22 | _clientLogger = new AuditLogger(AuditLogType.Client, writer, formatter); 23 | _serviceLogger = new AuditLogger(AuditLogType.Service, writer, formatter); 24 | } 25 | public IAuditLogger GetLogger(AuditLogType auditLogType) 26 | { 27 | return auditLogType == AuditLogType.Client ? _clientLogger : _serviceLogger; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/ICallInvoker.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Threading.Tasks; 5 | 6 | namespace DotBPE.Rpc.Client 7 | { 8 | 9 | public interface ICallInvoker : IMessageSubscriber 10 | { 11 | Task> InvokerAsync(IMethod method, TRequest request) 12 | where TRequest : class 13 | where TResponse : class; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/IClientMessageHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using Peach.Messaging; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace DotBPE.Rpc.Client 11 | { 12 | public interface IClientMessageHandler 13 | { 14 | 15 | void RaiseReceive(AmpMessage message); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/IClientProxy.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Rpc.Client 10 | { 11 | public interface IClientProxy 12 | { 13 | Task CreateAsync(ushort specialMessageId = 0) where TService : class; 14 | 15 | TService Create(ushort specialMessageId = 0) where TService : class; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/IClientProxyFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.Design; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace DotBPE.Rpc.Client 6 | { 7 | public interface IClientProxyFactory 8 | { 9 | IClientProxy GetClientProxy(); 10 | 11 | IClientProxyFactory AddDependencyServices(Action configServicesDelegate); 12 | 13 | 14 | IClientProxyFactory Configure(Action configureOptions) where TOption : class; 15 | 16 | TService GetService() where TService : class; 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/IMessageSubscriber.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotBPE.Rpc.Client 11 | { 12 | public interface IMessageSubscriber 13 | { 14 | void Handle(AmpMessage message); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/IMessageSubscriberContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc.Client 9 | { 10 | public interface IMessageSubscriberContainer 11 | { 12 | List GetMessageSubscribers(); 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/IRouterPoint.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Net; 6 | 7 | namespace DotBPE.Rpc.Client 8 | { 9 | public interface IRouterPoint 10 | { 11 | IPEndPoint RemoteAddress { get; } 12 | RoutePointType RoutePointType { get; } 13 | int Weight { get; } 14 | int FailCount { get; set; } 15 | bool Active { get; set; } 16 | } 17 | 18 | public class RouterPoint : IRouterPoint 19 | { 20 | public IPEndPoint RemoteAddress { get; set; } 21 | public RoutePointType RoutePointType { get; set; } 22 | public int FailCount { get; set; } 23 | public DateTime LastActiveTime { get; set; } 24 | public bool Active { get; set; } = true; 25 | 26 | public int Weight { get; set; } = 1; 27 | } 28 | 29 | public enum RoutePointType 30 | { 31 | Local, 32 | Remote 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/IRoutingPolicy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Text; 5 | 6 | namespace DotBPE.Rpc.Client 7 | { 8 | public interface IRoutingPolicy 9 | { 10 | IRouterPoint Select(string serviceKey, List remoteAddresses); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/IRpcClient.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using Peach.Messaging; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Rpc.Client 10 | { 11 | public interface IRpcClient 12 | { 13 | 14 | Task SendAsync(AmpMessage message); 15 | Task CloseAsync(CancellationToken cancellationToken); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/IServiceRouter.cs: -------------------------------------------------------------------------------- 1 | using Peach.Messaging; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DotBPE.Rpc.Client 8 | { 9 | /// 10 | /// 服务路由接口 11 | /// 12 | public interface IServiceRouter 13 | { 14 | Task FindRouterPoint(string servicePath); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/ITransport.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace DotBPE.Rpc.Client 9 | { 10 | public interface ITransport 11 | { 12 | Task SendAsync(AmpMessage request); 13 | 14 | Task CloseAsync(CancellationToken cancellationToken); 15 | 16 | string Id { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/ITransportFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Peach.Messaging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Net; 8 | using System.Text; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | namespace DotBPE.Rpc.Client 13 | { 14 | public interface ITransportFactory 15 | { 16 | Task CreateTransport(EndPoint endpoint); 17 | 18 | Task CloseTransportAsync(EndPoint endpoint); 19 | 20 | Task CloseAllTransports(CancellationToken cancellationToken); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/Impl/DefaultClientMessageHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace DotBPE.Rpc.Client 9 | { 10 | public class DefaultClientMessageHandler : IClientMessageHandler 11 | { 12 | 13 | private readonly IMessageSubscriberContainer _subscriberContainer; 14 | 15 | public DefaultClientMessageHandler(IMessageSubscriberContainer subscriberContainer) 16 | { 17 | _subscriberContainer = subscriberContainer; 18 | } 19 | 20 | public void RaiseReceive(AmpMessage message) 21 | { 22 | var subscribers = _subscriberContainer.GetMessageSubscribers(); 23 | if (subscribers?.Count > 0) 24 | { 25 | foreach (var subscriber in subscribers) 26 | { 27 | subscriber.Handle(message); 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/Impl/DefaultMessageSubscriberContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Microsoft.Extensions.DependencyInjection; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | 10 | namespace DotBPE.Rpc.Client.Impl 11 | { 12 | public class DefaultMessageSubscriberContainer : IMessageSubscriberContainer 13 | { 14 | private readonly List _subscribers; 15 | 16 | public DefaultMessageSubscriberContainer(IEnumerable subscribers) 17 | { 18 | _subscribers = subscribers.ToList(); 19 | 20 | } 21 | 22 | /// 23 | /// 24 | /// 25 | /// 26 | public void Subscribe(IMessageSubscriber subscriber) 27 | { 28 | _subscribers.Add(subscriber); 29 | } 30 | 31 | public List GetMessageSubscribers() 32 | { 33 | return _subscribers; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/Impl/DefaultTransport.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Baseline.Utility; 5 | using DotBPE.Rpc.Protocols; 6 | using Peach; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotBPE.Rpc.Client 11 | { 12 | internal class DefaultTransport : ITransport 13 | { 14 | private readonly ISocketContext _context; 15 | public DefaultTransport(ISocketContext context) 16 | { 17 | _context = context; 18 | Id = ObjectId.GenerateNewId().ToString(); 19 | } 20 | 21 | public string Id { get; } 22 | 23 | public Task CloseAsync(CancellationToken cancellationToken) 24 | { 25 | return _context.Channel.CloseAsync(); 26 | } 27 | 28 | public Task SendAsync(AmpMessage request) 29 | { 30 | return _context.SendAsync(request); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/Impl/RpcSocketClient.cs: -------------------------------------------------------------------------------- 1 | using DotBPE.Rpc.Protocols; 2 | using Microsoft.Extensions.Options; 3 | using Peach; 4 | using Peach.Tcp; 5 | 6 | namespace DotBPE.Rpc.Client 7 | { 8 | public class RpcSocketClient : TcpClient 9 | { 10 | public RpcSocketClient(IOptions clientOption, IChannelHandlerPipeline handlerPipeline) 11 | : base(clientOption, handlerPipeline) 12 | { 13 | 14 | } 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/RoutingPolicies/RandomRoutingPolicy.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace DotBPE.Rpc.Client.RoutingPolicies 8 | { 9 | public class RandomRoutingPolicy : IRoutingPolicy 10 | { 11 | private static Random Random = new Random(100000); 12 | public IRouterPoint Select(string serviceKey, List remoteAddresses) 13 | { 14 | int v = Random.Next(); 15 | int index = v % remoteAddresses.Count; 16 | return remoteAddresses[index]; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/RoutingPolicies/RoundrobinRoutingPolicy.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Collections.Concurrent; 5 | using System.Collections.Generic; 6 | 7 | namespace DotBPE.Rpc.Client.RoutingPolicies 8 | { 9 | public class RoundrobinRoutingPolicy : IRoutingPolicy 10 | { 11 | private static ConcurrentDictionary RoundCache = new ConcurrentDictionary(); 12 | 13 | public IRouterPoint Select(string serviceKey, List remoteAddresses) 14 | { 15 | if (!RoundCache.TryGetValue(serviceKey, out int index)) 16 | { 17 | RoundCache.TryAdd(serviceKey, index); 18 | } 19 | else 20 | { 21 | RoundCache.TryUpdate(serviceKey, index + 1, index); 22 | index++; 23 | } 24 | index %= remoteAddresses.Count; 25 | 26 | return remoteAddresses[index]; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Client/RoutingPolicies/WeightedRoundRobinRoutingPolicy.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Collections.Concurrent; 5 | using System.Collections.Generic; 6 | 7 | namespace DotBPE.Rpc.Client.RoutingPolicies 8 | { 9 | internal class WeightedRoundRobinRoutingPolicy 10 | { 11 | private static ConcurrentDictionary RoundCache = new ConcurrentDictionary(); 12 | 13 | public IRouterPoint Select(string serviceKey, List remoteAddresses) 14 | { 15 | var max = TotalWeight(remoteAddresses); 16 | if (!RoundCache.TryGetValue(serviceKey, out int index)) 17 | { 18 | RoundCache.TryAdd(serviceKey, index); 19 | return remoteAddresses[index]; 20 | } 21 | else 22 | { 23 | RoundCache.TryUpdate(serviceKey, index + 1, index); 24 | index++; 25 | } 26 | 27 | if (index == max) 28 | { 29 | index = 0; 30 | return remoteAddresses[index]; 31 | } 32 | 33 | int cur = 0; 34 | for (var i = 0; i < remoteAddresses.Count; i++) 35 | { 36 | cur += remoteAddresses[i].Weight; 37 | if (index <= cur) 38 | { 39 | return remoteAddresses[i]; 40 | } 41 | } 42 | return remoteAddresses[0]; 43 | } 44 | 45 | 46 | 47 | private static int TotalWeight(List remoteAddresses) 48 | { 49 | int total = 0; 50 | if (remoteAddresses.Count > 0) 51 | { 52 | for (var i = 0; i < remoteAddresses.Count; i++) 53 | { 54 | total += remoteAddresses[i].Weight; 55 | } 56 | } 57 | return total; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Codec/CodecType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc.Codec 9 | { 10 | public enum CodecType : byte 11 | { 12 | Protobuf = 0, 13 | MessagePack = 1, 14 | JSON = 2, 15 | Unknown = 9, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Codec/ISerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DotBPE.Rpc 6 | { 7 | public interface ISerializer 8 | { 9 | T Deserialize(byte[] data); 10 | byte[] Serialize(T item); 11 | object Deserialize(byte[] data,Type type); 12 | byte[] Serialize(object item); 13 | byte CodecType { get; } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/DotBPE.Rpc.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | netstandard2.0 6 | $(RpcPackageVersion) 7 | Xuanye @ 2017-2022 8 | Xuanye Wong 9 | Xuanye Wong 10 | icon.png 11 | microservice,dotnet,peach,rpc,dotbpe 12 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 13 | dotbpe.rpc is a lightweight and high performance, easy to learn rpc framework 14 | https://github.com/dotbpe/dotbpe 15 | https://raw.githubusercontent.com/dotbpe/dotbpe/master/LICENSE 16 | https://github.com/dotbpe/dotbpe.git 17 | git 18 | 19 | $(RpcPackageNotes) 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Exceptions/RpcCodecException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | 6 | namespace DotBPE.Rpc.Exceptions 7 | { 8 | /// 9 | /// codec exception 10 | /// 11 | public class RpcCodecException : Exception 12 | { 13 | public RpcCodecException() 14 | { 15 | } 16 | 17 | public RpcCodecException(string message) : base(message) 18 | { 19 | } 20 | 21 | public RpcCodecException(string message, Exception inner) : base(message, inner) 22 | { 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Exceptions/RpcCommunicationException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | 5 | using System; 6 | 7 | namespace DotBPE.Rpc.Exceptions 8 | { 9 | /// 10 | /// 11 | /// RPC通信异常类 12 | /// 13 | /// 14 | public class RpcCommunicationException : Exception 15 | { 16 | public RpcCommunicationException() 17 | { 18 | } 19 | 20 | public RpcCommunicationException(string message) : base(message) 21 | { 22 | } 23 | 24 | public RpcCommunicationException(string message, Exception inner) : base(message, inner) 25 | { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Exceptions/RpcException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using System; 6 | 7 | namespace DotBPE.Rpc.Exceptions 8 | { 9 | public class RpcException : Exception 10 | { 11 | public RpcException(string message) : this(RpcStatusCodes.CODE_INTERNAL_ERROR, message) 12 | { 13 | 14 | } 15 | public RpcException(int statusCode, string message) : base(message) 16 | { 17 | StatusCode = statusCode; 18 | } 19 | 20 | public RpcException(int statusCode, string message, Exception inner) : base(message, inner) 21 | { 22 | StatusCode = statusCode; 23 | } 24 | public int StatusCode { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Extensions/ClientProxyFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using DotBPE.Rpc.Client; 6 | using Microsoft.Extensions.Logging; 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | namespace Microsoft.Extensions.DependencyInjection 11 | { 12 | public static class ClientProxyFactoryExtensions 13 | { 14 | public static IClientProxyFactory UseDefaultChannel(this IClientProxyFactory @this, string remoteAddress) 15 | { 16 | 17 | return @this.UseChannel("default", remoteAddress); 18 | 19 | } 20 | public static IClientProxyFactory UseChannel(this IClientProxyFactory @this, string groupName, string remoteAddress) 21 | { 22 | 23 | return @this.Configure(o => 24 | { 25 | if (o.Categories == null) 26 | { 27 | o.Categories = new List(); 28 | } 29 | 30 | var channel = o.Categories.Find(x => x.GroupName == groupName); 31 | if (channel == null) 32 | { 33 | channel = new GroupIdentifierOption { GroupName = groupName }; 34 | o.Categories.Add(channel); 35 | } 36 | channel.RemoteAddress = remoteAddress; 37 | 38 | }); 39 | 40 | } 41 | public static IClientProxyFactory ConfigureLogging(this IClientProxyFactory @this, Action configure) 42 | { 43 | return @this.AddDependencyServices(services => services.AddLogging(configure)); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Extensions/HostBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using DotBPE.Rpc.Hosting; 6 | using DotBPE.Rpc.Protocols; 7 | using DotBPE.Rpc.Server; 8 | using Microsoft.Extensions.Hosting; 9 | using System; 10 | using System.Reflection; 11 | using System.Threading; 12 | using System.Threading.Tasks; 13 | 14 | namespace Microsoft.Extensions.DependencyInjection 15 | { 16 | public static class HostBuilderExtensions 17 | { 18 | public static IHostBuilder UseRpcServer(this IHostBuilder builder, Action configServer = null) 19 | { 20 | return builder.ConfigureServices(services => 21 | { 22 | services.AddDotBPEServer(configServer); 23 | }); 24 | } 25 | 26 | public static IHostBuilder BindService(this IHostBuilder builder) where TService : class, IServiceActor 27 | { 28 | return builder.ConfigureServices(services => services.BindService()); 29 | } 30 | 31 | public static IHostBuilder BindServices(this IHostBuilder builder, Func filterFunc = null) 32 | { 33 | return builder.ConfigureServices(services => services.BindServices(typeof(Assembly).Assembly, filterFunc)); 34 | } 35 | 36 | public static async Task RunServerAsync(this IHostBuilder builder, CancellationToken cancellationToken = default(CancellationToken)) 37 | { 38 | var host = builder.UseConsoleLifetime().Build(); 39 | var actorBuilder = host.Services.GetRequiredService(); 40 | actorBuilder.Build(); 41 | await host.RunAsync(cancellationToken); 42 | return host; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Hosting/AmpPeachSocketService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using DotBPE.Rpc.Server; 6 | using Microsoft.Extensions.Logging; 7 | using Peach; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace DotBPE.Rpc.Hosting 14 | { 15 | public class AmpPeachSocketService : AbsSocketService 16 | { 17 | private readonly IMessageHandler _messageHandler; 18 | private readonly ILogger _logger; 19 | public AmpPeachSocketService( 20 | IMessageHandler messageHandler, 21 | ILogger logger 22 | ) 23 | { 24 | _messageHandler = messageHandler; 25 | _logger = logger; 26 | } 27 | 28 | public override void OnReceive(ISocketContext context, AmpMessage msg) 29 | { 30 | _logger.LogDebug("receive message {id}", msg.Id); 31 | Task.Run(async () => 32 | { 33 | await _messageHandler.ReceiveAsync(context, msg); 34 | }).ConfigureAwait(false); 35 | } 36 | 37 | public override void OnException(ISocketContext context, Exception ex) 38 | { 39 | _logger.LogError(ex, "server error occ"); 40 | base.OnException(context, ex); 41 | } 42 | 43 | public override void OnDisconnected(ISocketContext context) 44 | { 45 | _logger.LogInformation("client disconnected from {address}", context.RemoteEndPoint.Address); 46 | base.OnDisconnected(context); 47 | } 48 | 49 | public override void OnConnected(ISocketContext context) 50 | { 51 | _logger.LogInformation("client connected from {address}", context.RemoteEndPoint.Address); 52 | base.OnConnected(context); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Hosting/PeachServerBootstrap.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using Microsoft.Extensions.Logging; 6 | using Microsoft.Extensions.Options; 7 | using Peach; 8 | using Peach.Tcp; 9 | 10 | namespace DotBPE.Rpc.Hosting 11 | { 12 | public class PeachServerBootstrap : TcpServerBootstrap 13 | { 14 | public PeachServerBootstrap( 15 | ISocketService socketService, 16 | IChannelHandlerPipeline handlerPipeline, 17 | ILoggerFactory loggerFactory, 18 | IOptions hostOption) 19 | : base(socketService, handlerPipeline, loggerFactory, hostOption) 20 | { 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Hosting/PeachServerHost.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | 5 | using DotBPE.Rpc.Server; 6 | using Peach; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotBPE.Rpc.Hosting 11 | { 12 | public class PeachServerHost : IServerHost 13 | { 14 | private readonly IServerBootstrap _server; 15 | 16 | public PeachServerHost(IServerBootstrap server) 17 | { 18 | _server = server; 19 | 20 | } 21 | 22 | public Task StartAsync(CancellationToken cancellationToken) 23 | { 24 | return _server.StartAsync(cancellationToken); 25 | } 26 | 27 | public Task StopAsync(CancellationToken cancellationToken) 28 | { 29 | return _server.StopAsync(cancellationToken); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Hosting/RpcServerOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Peach.Config; 5 | 6 | namespace DotBPE.Rpc.Hosting 7 | { 8 | public class RpcServerOptions : TcpHostOption 9 | { 10 | public RpcServerOptions() 11 | { 12 | StartupWords = "DotBPE Server bind at {0}\r\n"; 13 | AppName = "DotBPE"; 14 | } 15 | 16 | public static readonly RpcServerOptions Default = new RpcServerOptions() 17 | { 18 | Port = 5566, 19 | BindType = AddressBindType.Loopback 20 | }; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Hosting/RpcServiceHostedService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Server; 5 | using Microsoft.Extensions.Hosting; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Rpc.Hosting 10 | { 11 | internal class RpcServiceHostedService : IHostedService 12 | { 13 | private readonly IServerHost _server; 14 | 15 | public RpcServiceHostedService(IServerHost server) 16 | { 17 | _server = server; 18 | } 19 | 20 | public Task StartAsync(CancellationToken cancellationToken) 21 | { 22 | return _server.StartAsync(cancellationToken); 23 | } 24 | 25 | public Task StopAsync(CancellationToken cancellationToken) 26 | { 27 | return _server.StopAsync(cancellationToken); 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/IJsonParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc 9 | { 10 | public interface IJsonParser 11 | { 12 | string ToJson(object item); 13 | 14 | string ToJson(T item) where T : class; 15 | 16 | object FromJson(string json, Type type); 17 | 18 | T FromJson(string json) where T : class; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/IMethod.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc 9 | { 10 | public interface IMethod 11 | { 12 | string GroupName { get; } 13 | string ServiceName { get; } 14 | string MethodName { get; } 15 | int ServiceId { get; } 16 | ushort MethodId { get; } 17 | string FullName { get; } 18 | 19 | int DefaultTimeout { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/IRpcContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Net; 7 | using System.Text; 8 | 9 | namespace DotBPE.Rpc 10 | { 11 | public interface IRpcContext 12 | { 13 | IPEndPoint RemoteAddress { get; } 14 | IPEndPoint LocalAddress { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Internal/HeartBeatServiceActor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using DotBPE.Rpc.Server; 6 | using Peach; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace DotBPE.Rpc.Internal 13 | { 14 | public class HeartBeatServiceActor : IServiceActor 15 | { 16 | public static HeartBeatServiceActor Instance = new HeartBeatServiceActor(); 17 | public string Id => "0.0"; 18 | 19 | public string GroupName { get; } = "default"; 20 | 21 | 22 | public Task ReceiveAsync(ISocketContext context, AmpMessage message) 23 | { 24 | message.MessageType = RpcMessageType.Response; 25 | return context.SendAsync(message); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Internal/HeartBeatServiceActorHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using DotBPE.Rpc.Server; 6 | using Peach; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace DotBPE.Rpc.Internal 13 | { 14 | public class HeartBeatServiceActorHandler : IServiceActorHandler 15 | { 16 | 17 | public static HeartBeatServiceActorHandler Instance = new HeartBeatServiceActorHandler(); 18 | 19 | public Task HandleAsync(ISocketContext context, AmpMessage message) 20 | { 21 | return HeartBeatServiceActor.Instance.ReceiveAsync(context, message); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Internal/NotFoundServiceActor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using DotBPE.Rpc.Server; 6 | using Peach; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Rpc.Internal 10 | { 11 | public class NotFoundServiceActor : IServiceActor 12 | { 13 | public static NotFoundServiceActor Instance = new NotFoundServiceActor(); 14 | 15 | public string Id => "NotFoundServiceActor"; 16 | public string GroupName => "default"; 17 | 18 | public async Task ReceiveAsync(ISocketContext context, AmpMessage message) 19 | { 20 | var response = new AmpMessage 21 | { 22 | MessageType = RpcMessageType.Response, 23 | Code = RpcStatusCodes.CODE_SERVICE_NOT_FOUND, 24 | ServiceId = message.ServiceId, 25 | MessageId = message.MessageId, 26 | Sequence = message.Sequence 27 | }; 28 | await context.SendAsync(response); 29 | } 30 | 31 | public static bool IsNotFoundServiceActor(IServiceActor serviceActor) 32 | { 33 | return serviceActor.Id == Instance.Id; 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Internal/NotFoundServiceActorHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using DotBPE.Rpc.Server; 6 | using Peach; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace DotBPE.Rpc.Internal 13 | { 14 | public class NotFoundServiceActorHandler : IServiceActorHandler 15 | { 16 | public static NotFoundServiceActorHandler Instance = new NotFoundServiceActorHandler(); 17 | 18 | public Task HandleAsync(ISocketContext context, AmpMessage message) 19 | { 20 | return NotFoundServiceActor.Instance.ReceiveAsync(context, message); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Method.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Reflection; 8 | using System.Text; 9 | 10 | namespace DotBPE.Rpc 11 | { 12 | 13 | public class Method : IMethod 14 | { 15 | public string GroupName { get; set; } 16 | public string ServiceName { get; set; } 17 | public string MethodName { get; set; } 18 | 19 | public int ServiceId { get; set; } 20 | public ushort MethodId { get; set; } 21 | public int DefaultTimeout { get; set; } 22 | public string FullName => $"{ServiceName}.{MethodName}"; 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("DotBPE.Rpc.Tests")] 7 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Protocols/AmpChannelHandlerPipeline.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotNetty.Codecs; 5 | using DotNetty.Handlers.Timeout; 6 | using DotNetty.Transport.Channels; 7 | using Peach; 8 | using System.Collections.Generic; 9 | 10 | namespace DotBPE.Rpc.Protocols 11 | { 12 | public class AmpChannelHandlerPipeline : IChannelHandlerPipeline 13 | { 14 | private readonly ISerializer _serializer; 15 | 16 | public AmpChannelHandlerPipeline(ISerializer serializer) 17 | { 18 | _serializer = serializer; 19 | } 20 | public Dictionary BuildPipeline(bool isServer) 21 | { 22 | var timeOut = isServer ? AmpProtocol.HEARTBEAT_INTERVAL * 2 : AmpProtocol.HEARTBEAT_INTERVAL; 23 | return new Dictionary { 24 | 25 | { "timeout", new IdleStateHandler(0, 0,timeOut) }, 26 | 27 | { "message-enc", new AmpEncodeHandler(_serializer) }, 28 | { "framing-dec", new LengthFieldBasedFrameDecoder( 29 | AmpProtocol.MAX_FRAME_LENGTH, 30 | AmpProtocol.LENGTH_FIELD_OFFSET, 31 | AmpProtocol.LENGTH_FIELD_LENGTH, 32 | AmpProtocol.LENGTH_ADJUSTMENT, 33 | AmpProtocol.INITIAL_BYTES_TO_STRIP 34 | ) }, 35 | { "message-dec", new AmpDecodeHandler(_serializer) } 36 | }; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Protocols/AmpDecodeHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Codec; 5 | using DotBPE.Rpc.Exceptions; 6 | using DotNetty.Buffers; 7 | using DotNetty.Transport.Channels; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Text; 11 | 12 | namespace DotBPE.Rpc.Protocols 13 | { 14 | public class AmpDecodeHandler : DotNetty.Codecs.ByteToMessageDecoder 15 | { 16 | private readonly ISerializer _serializer; 17 | 18 | public AmpDecodeHandler(ISerializer serializer) 19 | { 20 | _serializer = serializer; 21 | } 22 | 23 | protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List output) 24 | { 25 | var msg = AmpProtocol.Decode((CodecType)_serializer.CodecType, input); 26 | if (msg == null) 27 | { 28 | return; 29 | } 30 | output.Add(msg); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Protocols/AmpEncodeHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Codec; 5 | using DotNetty.Buffers; 6 | using DotNetty.Transport.Channels; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | 11 | namespace DotBPE.Rpc.Protocols 12 | { 13 | public class AmpEncodeHandler : DotNetty.Codecs.MessageToByteEncoder 14 | { 15 | private readonly ISerializer _serializer; 16 | 17 | public AmpEncodeHandler(ISerializer serializer) 18 | { 19 | _serializer = serializer; 20 | } 21 | 22 | protected override void Encode(IChannelHandlerContext context, AmpMessage message, IByteBuffer output) 23 | { 24 | if (message == null) 25 | { 26 | return; 27 | } 28 | AmpProtocol.Encode(message, (CodecType)_serializer.CodecType, output); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Protocols/IRpcMessage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc.Protocols 9 | { 10 | public interface IRpcMessage 11 | { 12 | RpcMessageType MessageType { get; } 13 | 14 | int Length { get; } 15 | 16 | 17 | /// 18 | /// Service identifier to locate a service 19 | /// 20 | string ServiceIdentity { get; } 21 | 22 | /// 23 | /// Method identifier to locate a method 24 | /// 25 | string MethodIdentifier { get; } 26 | 27 | bool IsHeartBeat { get; } 28 | } 29 | 30 | public enum RpcMessageType : byte 31 | { 32 | Request = 1, 33 | Response = 2, 34 | Notify = 3, //Oneway Response 35 | OnewayRequest = 4 //Oneway Request 36 | } 37 | } -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Protocols/RpcStatusCodes.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc.Protocols 9 | { 10 | public static class RpcStatusCodes 11 | { 12 | /// 13 | /// Success 14 | /// 15 | public const int CODE_SUCCESS = 0; 16 | 17 | /// 18 | /// internal error 19 | /// 20 | public const int CODE_INTERNAL_ERROR = -10242500; 21 | 22 | /// 23 | /// 拒绝访问 24 | /// 25 | public const int CODE_ACCESS_DENIED = -10242403; 26 | 27 | /// 28 | /// service not found 29 | /// 30 | public const int CODE_SERVICE_NOT_FOUND = -10242404; 31 | 32 | /// 33 | /// rate limited 34 | /// 35 | public const int CODE_RATE_LIMITED = -10242409; 36 | 37 | /// 38 | /// timeout 39 | /// 40 | public const int CODE_TIMEOUT = -10242504; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/RouterPointOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc 9 | { 10 | public class RouterPointOptions 11 | { 12 | public List Categories { get; set; } 13 | public List Services { get; set; } 14 | public List Messages { get; set; } 15 | 16 | } 17 | 18 | public class GroupIdentifierOption 19 | { 20 | public string GroupName { get; set; } 21 | public string RemoteAddress { get; set; } 22 | public int Weight { get; set; } = 1; 23 | } 24 | 25 | public class ServiceIdentifierOption 26 | { 27 | public int ServiceId { get; set; } 28 | public string RemoteAddress { get; set; } 29 | public int Weight { get; set; } = 1; 30 | } 31 | 32 | public class MessageIdentifierOption 33 | { 34 | public int ServiceId { get; set; } 35 | public int MessageId { get; set; } 36 | public string RemoteAddress { get; set; } 37 | public int Weight { get; set; } = 1; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/RpcClientOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace DotBPE.Rpc 6 | { 7 | public class RpcClientOptions : Peach.Config.TcpClientOption 8 | { 9 | public string AppName { get; set; } = "dotbpe"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/RpcResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Runtime.Serialization; 7 | using System.Text; 8 | using System.Xml.Linq; 9 | 10 | namespace DotBPE.Rpc 11 | { 12 | public class RpcResult 13 | { 14 | public int Code 15 | { 16 | get; set; 17 | } 18 | } 19 | 20 | public class RpcResult : RpcResult where T : class 21 | { 22 | public T Data 23 | { 24 | get; set; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/ActorInvokerModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | namespace DotBPE.Rpc.Server 5 | { 6 | public class ActorInvokerModel 7 | { 8 | 9 | public ActorInvokerModel(IMethod method, RequestDelegate requestDelegate) 10 | { 11 | 12 | RequestDelegate = requestDelegate; 13 | Method = method; 14 | } 15 | 16 | public string MethodIdentifier => $"{Method.ServiceId}.{Method.MethodId}"; 17 | public IMethod Method { get; } 18 | 19 | public RequestDelegate RequestDelegate { get; } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/ICallContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc.Server 9 | { 10 | public interface ICallContext : IDisposable 11 | { 12 | bool ContainsKey(string key); 13 | 14 | 15 | object Get(string key); 16 | 17 | 18 | void Remove(string key); 19 | 20 | void AddOrUpdate(string key, object item); 21 | 22 | 23 | void AddDef(); 24 | void CloseDef(); 25 | } 26 | public class CallContext : ICallContext 27 | { 28 | private readonly Dictionary _items; 29 | 30 | private int _refCount; 31 | 32 | public CallContext() 33 | { 34 | _items = new Dictionary(); 35 | } 36 | 37 | 38 | public bool ContainsKey(string key) 39 | { 40 | return _items.ContainsKey(key); 41 | } 42 | 43 | public object Get(string key) 44 | { 45 | if (ContainsKey(key)) 46 | { 47 | return _items[key]; 48 | } 49 | return null; 50 | } 51 | 52 | public void Remove(string key) 53 | { 54 | if (ContainsKey(key)) 55 | { 56 | _items.Remove(key); 57 | } 58 | } 59 | 60 | 61 | public void Dispose() 62 | { 63 | _items.Clear(); 64 | } 65 | 66 | public void AddOrUpdate(string key, object item) 67 | { 68 | 69 | if (ContainsKey(key)) 70 | { 71 | _items[key] = item; 72 | } 73 | else 74 | { 75 | _items.Add(key, item); 76 | } 77 | } 78 | 79 | public void AddDef() 80 | { 81 | _refCount++; 82 | } 83 | 84 | public void CloseDef() 85 | { 86 | _refCount--; 87 | if (_refCount <= 0) 88 | { 89 | Dispose(); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/IContextAccessor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading; 8 | 9 | namespace DotBPE.Rpc.Server 10 | { 11 | public interface IContextAccessor 12 | { 13 | ICallContext CallContext { get; set; } 14 | } 15 | 16 | public class DefaultContextAccessor : IContextAccessor 17 | { 18 | private static readonly AsyncLocal _callContextCurrent = new AsyncLocal(); 19 | 20 | public ICallContext CallContext 21 | { 22 | get 23 | { 24 | return _callContextCurrent.Value; 25 | } 26 | 27 | set 28 | { 29 | _callContextCurrent.Value = value; 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/IMessageHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Peach; 5 | using Peach.Messaging; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace DotBPE.Rpc.Server 12 | { 13 | public interface IMessageHandler where TMessage : IMessage 14 | { 15 | Task ReceiveAsync(ISocketContext context, TMessage message); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/IServerHost.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotBPE.Rpc.Server 11 | { 12 | public interface IServerHost 13 | { 14 | Task StartAsync(CancellationToken cancellationToken); 15 | Task StopAsync(CancellationToken cancellationToken); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/IServiceActor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | namespace DotBPE.Rpc.Server 5 | { 6 | public interface IServiceActor 7 | { 8 | string Id { get; } 9 | 10 | string GroupName { get; } 11 | } 12 | 13 | public interface IServiceActor : IServiceActor where TService : class 14 | { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/IServiceActorBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Baseline.Extensions; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using System; 7 | using System.Diagnostics; 8 | using System.Linq; 9 | using System.Reflection; 10 | 11 | namespace DotBPE.Rpc.Server 12 | { 13 | public interface IServiceActorBuilder 14 | { 15 | void Build(); 16 | } 17 | 18 | 19 | public class ServiceActorBuilder : IServiceActorBuilder 20 | { 21 | private readonly IServiceProvider _provider; 22 | private readonly IServiceActorHandlerFactory _actorHandlerFactory; 23 | 24 | public ServiceActorBuilder(IServiceProvider provider, IServiceActorHandlerFactory actorHandlerFactory) 25 | { 26 | _provider = provider; 27 | _actorHandlerFactory = actorHandlerFactory; 28 | } 29 | 30 | public void Build() 31 | { 32 | var actors = _provider.GetServices(); 33 | actors.ForEach(actor => 34 | { 35 | BuildServiceActor(actor.GetType()); 36 | }); 37 | } 38 | 39 | private void BuildServiceActor(Type actorType) 40 | { 41 | var serviceActorProviderType = typeof(ServiceActorProvider<>); 42 | 43 | var serviceType = actorType.GetInterfaces().FirstOrDefault(x => x.GetCustomAttribute() != null); 44 | if (serviceType != null) 45 | { 46 | var serviceActorProvider = _provider.GetRequiredService(serviceActorProviderType.MakeGenericType(serviceType)) as IServiceActorProvider; 47 | 48 | Debug.Assert(serviceActorProvider != null, nameof(serviceActorProvider) + " != null"); 49 | 50 | serviceActorProvider.OnServiceActorDiscovery(new ServiceActorProviderContext(_actorHandlerFactory)); 51 | } 52 | 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/IServiceActorHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using Peach; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace DotBPE.Rpc.Server 12 | { 13 | public interface IServiceActorHandler 14 | { 15 | Task HandleAsync(ISocketContext context, AmpMessage message); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/IServiceActorHandlerFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Server; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace DotBPE.Rpc.Server 10 | { 11 | public interface IServiceActorHandlerFactory 12 | { 13 | IServiceActorHandler GetInstance(string methodIdentifier); 14 | void RegisterActorInvokerHandler(ActorInvokerModel actorModel); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/IServiceActorLocator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Peach.Messaging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotBPE.Rpc.Server 11 | { 12 | 13 | /// 14 | /// 服务定位器,实现者需要根据message中的内容,准确的找到具体的IServiceActor 15 | /// 16 | public interface IServiceActorLocator 17 | { 18 | /// 19 | /// Locating a ServiceActor by Id 20 | /// 21 | /// service actor id 22 | /// IServiceActor 23 | IServiceActor LocateServiceActor(string actorId); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/IServiceActorProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using Peach.Messaging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace DotBPE.Rpc.Server 10 | { 11 | public interface IServiceActorProvider 12 | { 13 | void OnServiceActorDiscovery(ServiceActorProviderContext context); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/Impl/BaseService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | 5 | using System; 6 | using System.Reflection; 7 | 8 | namespace DotBPE.Rpc.Server 9 | { 10 | public class BaseService : IServiceActor 11 | where TService : class 12 | { 13 | protected BaseService() 14 | { 15 | var serviceType = typeof(TService); 16 | var serviceAttribute = GetServiceAttribute(serviceType); 17 | ServiceId = serviceAttribute.ServiceId; 18 | GroupName = serviceAttribute.GroupName; 19 | } 20 | 21 | protected int ServiceId 22 | { 23 | get; 24 | } 25 | public string Id => $"{ServiceId}.0"; 26 | 27 | public string GroupName 28 | { 29 | get; 30 | } 31 | 32 | private static RpcServiceAttribute GetServiceAttribute(Type serviceType) 33 | { 34 | var serviceAttribute = serviceType.GetCustomAttribute(false); 35 | if (serviceAttribute == null) 36 | throw new InvalidOperationException($"Miss [RpcServiceAttribute] at {serviceType}"); 37 | return serviceAttribute; 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/Impl/DefaultMessageHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Internal; 5 | using DotBPE.Rpc.Protocols; 6 | using Microsoft.Extensions.Logging; 7 | using Peach; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotBPE.Rpc.Server 11 | { 12 | public class DefaultMessageHandler : IMessageHandler 13 | { 14 | private readonly IServiceActorHandlerFactory _actorHandlerFactory; 15 | private readonly ILogger _logger; 16 | 17 | public DefaultMessageHandler(IServiceActorHandlerFactory actorHandlerFactory, ILogger logger) 18 | { 19 | _actorHandlerFactory = actorHandlerFactory; 20 | _logger = logger; 21 | } 22 | public Task ReceiveAsync(ISocketContext context, AmpMessage message) 23 | { 24 | _logger.LogDebug("Received a message from {RemoteAddress},messageId={MessageId}", context.RemoteEndPoint, message.Id); 25 | if (message.MessageType == RpcMessageType.Response) 26 | return Task.CompletedTask; 27 | 28 | if (message.IsHeartBeat) 29 | { 30 | return HeartBeatServiceActorHandler.Instance.HandleAsync(context, message); 31 | } 32 | 33 | var handler = _actorHandlerFactory.GetInstance(message.MethodIdentifier); 34 | if (handler != null) 35 | return handler.HandleAsync(context, message); 36 | 37 | _logger.LogWarning("The service actor hander is not found,MethodId={methodIdentifier}", message.MethodIdentifier); 38 | return NotFoundServiceActorHandler.Instance.HandleAsync(context, message); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/Impl/DefaultServiceActorHandlerFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Internal; 5 | using Microsoft.Extensions.Logging; 6 | using System.Collections.Concurrent; 7 | 8 | namespace DotBPE.Rpc.Server 9 | { 10 | public class DefaultServiceActorHandlerFactory : IServiceActorHandlerFactory 11 | { 12 | private static readonly ConcurrentDictionary _invokerCache = new ConcurrentDictionary(); 13 | private static readonly ConcurrentDictionary _handlerCache = new ConcurrentDictionary(); 14 | private readonly ILogger _logger; 15 | 16 | public DefaultServiceActorHandlerFactory(ILogger logger) 17 | { 18 | _logger = logger; 19 | } 20 | 21 | public IServiceActorHandler GetInstance(string methodIdentifier) 22 | { 23 | if (_handlerCache.TryGetValue(methodIdentifier, out var handler)) 24 | return handler; 25 | 26 | if (!_invokerCache.TryGetValue(methodIdentifier, out var invoker)) 27 | return NotFoundServiceActorHandler.Instance; 28 | 29 | handler = new ServiceActorHandler(invoker); 30 | _handlerCache.TryAdd(methodIdentifier, handler); 31 | return handler; 32 | } 33 | 34 | public void RegisterActorInvokerHandler(ActorInvokerModel actorModel) 35 | { 36 | if (!_invokerCache.TryAdd(actorModel.MethodIdentifier, actorModel)) 37 | { 38 | _logger.LogWarning("{MethodFullName} has registration conflicts", actorModel.Method.FullName); 39 | } 40 | else 41 | { 42 | _logger.LogDebug("{MethodFullName} has been registered", actorModel.Method.FullName); 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/Impl/MethodInvoker.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | namespace DotBPE.Rpc.Server 8 | { 9 | public class MethodInvoker 10 | where TService : class 11 | where TRequest : class 12 | where TResponse : class 13 | { 14 | private readonly ServiceMethod _invoker; 15 | private readonly ServiceMethodWithTimeout _invokerWithTimeout; 16 | private readonly int _timeout; 17 | 18 | public MethodInvoker( 19 | ServiceMethod invoker, 20 | ServiceMethodWithTimeout invokerWithTimeout, 21 | int timeout 22 | ) 23 | { 24 | _invoker = invoker; 25 | _invokerWithTimeout = invokerWithTimeout; 26 | _timeout = timeout; 27 | } 28 | 29 | public async Task> InvokeAsync(TService service, TRequest request) 30 | { 31 | if (_invoker != null) 32 | return await _invoker.Invoke(service, request); 33 | if (_invokerWithTimeout != null) 34 | return await _invokerWithTimeout.Invoke(service, request, _timeout); 35 | 36 | throw new InvalidOperationException("There is no method invoker"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/Impl/RpcContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Net; 7 | using System.Text; 8 | 9 | namespace DotBPE.Rpc.Server 10 | { 11 | public class RpcContext : IRpcContext 12 | { 13 | public RpcContext(IPEndPoint remoteAddress, IPEndPoint localAddress) 14 | { 15 | RemoteAddress = remoteAddress; 16 | LocalAddress = localAddress; 17 | } 18 | 19 | public IPEndPoint RemoteAddress { get; set; } 20 | 21 | public IPEndPoint LocalAddress { get; set; } 22 | } 23 | 24 | public class LocalRpcContext : IRpcContext 25 | { 26 | 27 | public static readonly LocalRpcContext Instance = new LocalRpcContext(); 28 | 29 | private static readonly IPEndPoint _loopbackPoint = new IPEndPoint(IPAddress.Loopback, 0); 30 | 31 | public IPEndPoint RemoteAddress => _loopbackPoint; 32 | 33 | public IPEndPoint LocalAddress => _loopbackPoint; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/Impl/ServerMethod.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Reflection; 7 | using System.Text; 8 | 9 | namespace DotBPE.Rpc.Server.Impl 10 | { 11 | internal class ServerMethod : Method 12 | { 13 | public MethodInfo Handler { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/Impl/ServiceActorHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | 5 | using DotBPE.Rpc.Protocols; 6 | using Peach; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotBPE.Rpc.Server 10 | { 11 | public class ServiceActorHandler : IServiceActorHandler 12 | { 13 | 14 | private readonly ActorInvokerModel _invoker; 15 | 16 | public ServiceActorHandler(ActorInvokerModel invoker) 17 | { 18 | _invoker = invoker; 19 | } 20 | 21 | public Task HandleAsync(ISocketContext context, AmpMessage message) 22 | { 23 | return _invoker.RequestDelegate(context, message); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/RequestDelegate.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Protocols; 5 | using Peach; 6 | using System.Threading.Tasks; 7 | 8 | namespace DotBPE.Rpc.Server 9 | { 10 | public delegate Task RequestDelegate(ISocketContext context, AmpMessage message); 11 | 12 | public delegate Task> ServiceMethod(TService service, TRequest request) 13 | where TService : class 14 | where TRequest : class 15 | where TResponse : class; 16 | 17 | public delegate Task> ServiceMethodWithTimeout(TService service, TRequest request, int timeout) 18 | where TService : class 19 | where TRequest : class 20 | where TResponse : class; 21 | } -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/ServiceActorProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.AuditLog; 5 | using Microsoft.Extensions.Logging; 6 | using System; 7 | 8 | namespace DotBPE.Rpc.Server 9 | { 10 | public class ServiceActorProvider : IServiceActorProvider 11 | where TService : class 12 | { 13 | private readonly IServiceActorLocator _actorLocator; 14 | private readonly ISerializer _serializer; 15 | private readonly ILoggerFactory _loggerFactory; 16 | private readonly IAuditLoggerFactory _auditLoggerFactory; 17 | 18 | public ServiceActorProvider(IServiceActorLocator actorLocator 19 | , ISerializer serializer 20 | , ILoggerFactory loggerFactory 21 | , IAuditLoggerFactory auditLoggerFactory = null) 22 | { 23 | _actorLocator = actorLocator; 24 | _serializer = serializer; 25 | _loggerFactory = loggerFactory; 26 | _auditLoggerFactory = auditLoggerFactory; 27 | } 28 | 29 | 30 | public void OnServiceActorDiscovery(ServiceActorProviderContext context) 31 | { 32 | try 33 | { 34 | 35 | var binder = new ServiceActorBinder(context, _actorLocator, _serializer, _loggerFactory, _auditLoggerFactory); 36 | binder.Bind(); 37 | 38 | } 39 | catch (Exception ex) 40 | { 41 | throw new InvalidOperationException($"Error binding RPC service '{typeof(TService).Name}'.", ex); 42 | } 43 | } 44 | 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/Server/ServiceActorProviderContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | namespace DotBPE.Rpc.Server 5 | { 6 | public class ServiceActorProviderContext 7 | { 8 | private readonly IServiceActorHandlerFactory _handlerFactory; 9 | 10 | public ServiceActorProviderContext(IServiceActorHandlerFactory handlerFactory) 11 | { 12 | _handlerFactory = handlerFactory; 13 | } 14 | 15 | 16 | public void AddActorHandler(ActorInvokerModel actorModel) 17 | { 18 | _handlerFactory.RegisterActorInvokerHandler(actorModel); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/DotBPE.Rpc/ServiceModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc 9 | { 10 | public class ServiceModel 11 | { 12 | public int ServiceId { get; set; } 13 | 14 | public string Group { get; set; } 15 | 16 | public Type ServiceType { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/DotBPE.Extra.Castle.Tests/DotBPE.Extra.Castle.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/DotBPE.Extra.Castle.Tests/TestObjects/LogInterceptor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotBPE.Extra.Castle.Tests.TestObjects 11 | { 12 | public class LogInterceptor : ClientInterceptor 13 | { 14 | private readonly Action _logAction; 15 | 16 | public LogInterceptor(Action logAction) 17 | { 18 | _logAction = logAction; 19 | } 20 | 21 | protected override async Task> ServiceHandle(TRequest req, InvocationContext context, ServiceMethod continuation) 22 | { 23 | var res = await continuation(req, context); 24 | 25 | _logAction(req, res); 26 | return res; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/DotBPE.Gateway.Tests/DotBPE.Gateway.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0;net8.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/DotBPE.Gateway.Tests/TestObjects/DefaultJsonSerializer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using System; 6 | using System.Text.Json; 7 | 8 | namespace DotBPE.Gateway.Tests.TestObjects 9 | { 10 | public class DefaultJsonParser : IJsonParser 11 | { 12 | private static readonly JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions 13 | { 14 | #if NET5_0_OR_GREATER 15 | DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, 16 | #else 17 | IgnoreNullValues = true, 18 | #endif 19 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 20 | WriteIndented = false, 21 | IgnoreReadOnlyProperties = false, 22 | AllowTrailingCommas = false 23 | }; 24 | 25 | public string ToJson(object item) 26 | { 27 | return JsonSerializer.Serialize(item, _jsonSerializerOptions); 28 | } 29 | 30 | public string ToJson(T item) where T : class 31 | { 32 | return JsonSerializer.Serialize(item, _jsonSerializerOptions); 33 | } 34 | 35 | public object FromJson(string json, Type type) 36 | { 37 | return JsonSerializer.Deserialize(json, type, _jsonSerializerOptions); 38 | } 39 | 40 | public T FromJson(string json) where T : class 41 | { 42 | return JsonSerializer.Deserialize(json, _jsonSerializerOptions); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/DotBPE.Gateway.Tests/TestObjects/IInvalidPatternTestService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using System.Threading.Tasks; 6 | 7 | namespace DotBPE.Gateway.Tests.TestObjects 8 | { 9 | 10 | [RpcService(102)] 11 | public interface IInvalidPatternTestService 12 | { 13 | /// 14 | /// BadPattern 15 | /// 16 | /// request data 17 | /// 18 | [RpcMethod(4)] 19 | [HttpRoute("api/test/{id}")] 20 | Task> BadPatternAsync(Test1Req req); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/DotBPE.Rpc.Tests/Client/ClientProxyFactoryTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace DotBPE.Rpc.Tests.Client 9 | { 10 | public class ClientProxyFactoryTests 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/DotBPE.Rpc.Tests/Client/DefaultClientMessageHandlerTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Client; 5 | using DotBPE.Rpc.Client.Impl; 6 | using DotBPE.Rpc.Protocols; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Moq; 9 | using Xunit; 10 | 11 | namespace DotBPE.Rpc.Tests.Client 12 | { 13 | public class DefaultClientMessageHandlerTests 14 | { 15 | [Fact] 16 | public void RaiseReceive_SubscribersReceiveSameMessage() 17 | { 18 | //arrange 19 | var services = new ServiceCollection(); 20 | services.AddSingleton(); 21 | services.AddSingleton(); 22 | 23 | var msg = AmpMessage.CreateResponseMessage("100|1"); 24 | 25 | 26 | var subscriber1 = new Mock(); 27 | var subscriber2 = new Mock(); 28 | 29 | AmpMessage receivedMessage1 = null; 30 | AmpMessage receivedMessage2 = null; 31 | subscriber1.Setup(x => x.Handle(It.IsAny())).Callback((AmpMessage m1) => 32 | { 33 | receivedMessage1 = m1; 34 | }); 35 | subscriber2.Setup(x => x.Handle(It.IsAny())).Callback((AmpMessage m2) => 36 | { 37 | receivedMessage2 = m2; 38 | }); 39 | 40 | services.AddSingleton(subscriber1.Object); 41 | services.AddSingleton(subscriber2.Object); 42 | 43 | //act 44 | var provider = services.BuildServiceProvider(); 45 | var messageHandler = provider.GetRequiredService(); 46 | messageHandler.RaiseReceive(msg); 47 | 48 | //assert 49 | Assert.NotNull(receivedMessage1); 50 | Assert.NotNull(receivedMessage2); 51 | Assert.Equal(msg, receivedMessage1); 52 | Assert.Equal(msg, receivedMessage2); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/DotBPE.Rpc.Tests/DotBPE.Rpc.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | false 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | all 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/DotBPE.Rpc.Tests/Protocols/AmpProtocolTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc.Codec; 5 | using DotBPE.Rpc.Protocols; 6 | using DotNetty.Buffers; 7 | using Moq; 8 | using System.IO; 9 | using Xunit; 10 | 11 | namespace DotBPE.Rpc.Tests.Protocol 12 | { 13 | public class AmpProtocolTests 14 | { 15 | [Fact] 16 | public void EncodeAndDecode_ShouldBeOk() 17 | { 18 | var codecType = CodecType.MessagePack; 19 | /**/ 20 | var src = AmpMessage.CreateRequestMessage(1, 1, codecType, true); 21 | src.Version = 1; 22 | src.Code = 100; 23 | src.Sequence = 11; 24 | src.CodecType = codecType; 25 | src.Data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 26 | 27 | var buffer = Unpooled.Buffer(src.Length); 28 | 29 | AmpProtocol.Encode(src, codecType, buffer); 30 | 31 | var buffer2 = Unpooled.WrappedBuffer(buffer); 32 | var dist = AmpProtocol.Decode(codecType, buffer2); 33 | 34 | Assert.NotNull(dist); 35 | 36 | Assert.Equal(src.Id, dist.Id); 37 | Assert.Equal(src.Version, dist.Version); 38 | Assert.Equal(src.Code, dist.Code); 39 | Assert.Equal(src.Sequence, dist.Sequence); 40 | Assert.Equal(src.CodecType, dist.CodecType); 41 | Assert.Equal(src.Data.Length, dist.Data.Length); 42 | 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/DotBPE.TestBase/DotBPE.TestBase.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/DotBPE.TestBase/Services/FooService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using DotBPE.Rpc.Server; 6 | using System.Threading.Tasks; 7 | 8 | 9 | namespace DotBPE.TestBase 10 | { 11 | public class FooService : BaseService, IFooService 12 | { 13 | public Task> FooAsync(FooReq req) 14 | { 15 | return Task.FromResult(new RpcResult { Data = new FooRes { RetFooWord = req.FooWord } }); 16 | } 17 | } 18 | 19 | public class FooReq 20 | { 21 | public string FooWord 22 | { 23 | get; set; 24 | } 25 | } 26 | public class FooRes 27 | { 28 | public string RetFooWord 29 | { 30 | get; set; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/DotBPE.TestBase/Services/IFooService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using DotBPE.Rpc.Server; 6 | using System.Threading.Tasks; 7 | 8 | namespace DotBPE.TestBase 9 | { 10 | [RpcService(100, GroupName = "test")] 11 | public interface IFooService : IServiceActor 12 | { 13 | [RpcMethod(1)] 14 | Task> FooAsync(FooReq req); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/DotBPE.TestBase/TextJsonSerializer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Xuanye Wong. All rights reserved. 2 | // Licensed under MIT license 3 | 4 | using DotBPE.Rpc; 5 | using System; 6 | using System.Text; 7 | using System.Text.Json; 8 | 9 | namespace DotBPE.TestBase 10 | { 11 | public class DefaultJsonSerializer : ISerializer 12 | { 13 | public T Deserialize(byte[] data) 14 | { 15 | if (data == null) 16 | { 17 | return default; 18 | } 19 | var json = Encoding.UTF8.GetString(data); 20 | return JsonSerializer.Deserialize(json); 21 | } 22 | 23 | public byte[] Serialize(T item) 24 | { 25 | if (item == null) 26 | { 27 | return null; 28 | } 29 | return JsonSerializer.SerializeToUtf8Bytes(item); 30 | } 31 | 32 | public object Deserialize(byte[] data, Type type) 33 | { 34 | if (data == null) 35 | { 36 | return null; 37 | } 38 | var json = Encoding.UTF8.GetString(data); 39 | return JsonSerializer.Deserialize(json, type); 40 | } 41 | 42 | public byte[] Serialize(object item) 43 | { 44 | if (item == null) 45 | { 46 | return null; 47 | } 48 | return JsonSerializer.SerializeToUtf8Bytes(item); 49 | } 50 | 51 | public byte CodecType => (byte)Rpc.Codec.CodecType.JSON; 52 | } 53 | } 54 | --------------------------------------------------------------------------------