新增协议解析

pull/1/head
wangshaoming 7 years ago
parent b272b54fbd
commit 822b1fbe16
No known key found for this signature in database
GPG Key ID: 29F5223B4DB362B5
  1. 59
      DotXxlJob.sln
  2. BIN
      samples/ASPNetCoreExecutor/1547621183.dat
  3. 7
      samples/ASPNetCoreExecutor/ASPNetCoreExecutor.csproj
  4. 27
      samples/ASPNetCoreExecutor/Properties/launchSettings.json
  5. 11
      samples/ASPNetCoreExecutor/XxlJobExecutorMiddleware.cs
  6. BIN
      samples/HessianReader/1547620263.dat
  7. BIN
      samples/HessianReader/1547621183.dat
  8. 13
      samples/HessianReader/HessianReader.csproj
  9. 82
      samples/HessianReader/Program.cs
  10. BIN
      samples/HessianReader/kill.dat
  11. BIN
      samples/HessianReader/log.dat
  12. 0
      samples/HessianReader/run.dat
  13. 154
      src/DotXxlJob.Core/AdminClient.cs
  14. 3
      src/DotXxlJob.Core/CallbackTaskQueue.cs
  15. 2
      src/DotXxlJob.Core/Constants.cs
  16. 3
      src/DotXxlJob.Core/DotXxlJob.Core.csproj
  17. 193
      src/DotXxlJob.Core/HessianSerializer.cs
  18. 2
      src/DotXxlJob.Core/JobDispatcher.cs
  19. 39
      src/DotXxlJob.Core/Model/AddressEntity.cs
  20. 17
      src/DotXxlJob.Core/Model/HandleCallbackParam.cs
  21. 11
      src/DotXxlJob.Core/Model/HessianArrayList.cs
  22. 11
      src/DotXxlJob.Core/Model/JavaClass.cs
  23. 17
      src/DotXxlJob.Core/Model/LogResult.cs
  24. 16
      src/DotXxlJob.Core/Model/RegistryParam.cs
  25. 21
      src/DotXxlJob.Core/Model/ReturnT.cs
  26. 7
      src/DotXxlJob.Core/Model/RpcRequest.cs
  27. 26
      src/DotXxlJob.Core/Model/TriggerParam.cs
  28. 1
      src/DotXxlJob.Core/ServiceCollectionExtensions.cs
  29. 1
      src/DotXxlJob.Core/TaskQueue.cs
  30. 21
      src/DotXxlJob.Core/XxlRpcServiceHandler.cs
  31. 11
      src/Hessian.NET/HessianInputReader.cs
  32. 6
      src/Hessian.NET/HessianSerializationScheme.cs
  33. 32
      src/Hessian.NET/ListElement.cs
  34. 15
      src/Hessian.NET/ObjectElement.cs
  35. 11
      src/Hessian/ClassElement.cs
  36. 56
      src/Hessian/DateTimeExtension.cs
  37. 86
      src/Hessian/Deserializer.cs
  38. 2
      src/Hessian/Hessian.csproj
  39. 15
      src/Hessian/HessianObject.cs
  40. 27
      src/Hessian/HessianSerializationContext.cs
  41. 24
      src/Hessian/Main.cs
  42. 39
      src/Hessian/Marker.cs
  43. 31
      src/Hessian/PropertyElement.cs
  44. 517
      src/Hessian/Serializer.cs

@ -5,21 +5,17 @@ VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{97756BA5-1E7C-4536-A49E-AE2190C0E6A5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotXxlJob.Core", "src\DotXxlJob.Core\DotXxlJob.Core.csproj", "{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hessian.NET", "src\Hessian.NET\Hessian.NET.csproj", "{86456232-19D5-48DD-AC39-A0526517E0AD}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotXxlJob.Core", "src\DotXxlJob.Core\DotXxlJob.Core.csproj", "{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{352EC932-F112-4A2F-9DC3-F0761C85E068}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hessian.NET.Tests", "tests\Hessian.NET.Tests\Hessian.NET.Tests.csproj", "{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E959F9B5-F3EB-48B1-B842-2CDDFDB01900}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASPNetCoreExecutor", "samples\ASPNetCoreExecutor\ASPNetCoreExecutor.csproj", "{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASPNetCoreExecutor", "samples\ASPNetCoreExecutor\ASPNetCoreExecutor.csproj", "{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HessianReader", "samples\HessianReader\HessianReader.csproj", "{F822B528-95FD-40B4-9EE0-3AE8878075AC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HessianReader", "samples\HessianReader\HessianReader.csproj", "{F822B528-95FD-40B4-9EE0-3AE8878075AC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hessian", "src\Hessian\Hessian.csproj", "{BD9B8108-6528-430F-AD28-6F8434A29F55}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hessian", "src\Hessian\Hessian.csproj", "{BD9B8108-6528-430F-AD28-6F8434A29F55}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -30,17 +26,6 @@ Global
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
{86456232-19D5-48DD-AC39-A0526517E0AD} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9} = {352EC932-F112-4A2F-9DC3-F0761C85E068}
{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5} = {E959F9B5-F3EB-48B1-B842-2CDDFDB01900}
{F822B528-95FD-40B4-9EE0-3AE8878075AC} = {E959F9B5-F3EB-48B1-B842-2CDDFDB01900}
{BD9B8108-6528-430F-AD28-6F8434A29F55} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65}.Debug|Any CPU.Build.0 = Debug|Any CPU
@ -54,30 +39,6 @@ Global
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65}.Release|x64.Build.0 = Release|Any CPU
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65}.Release|x86.ActiveCfg = Release|Any CPU
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65}.Release|x86.Build.0 = Release|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Debug|x64.ActiveCfg = Debug|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Debug|x64.Build.0 = Debug|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Debug|x86.ActiveCfg = Debug|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Debug|x86.Build.0 = Debug|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Release|Any CPU.Build.0 = Release|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Release|x64.ActiveCfg = Release|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Release|x64.Build.0 = Release|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Release|x86.ActiveCfg = Release|Any CPU
{86456232-19D5-48DD-AC39-A0526517E0AD}.Release|x86.Build.0 = Release|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Debug|x64.ActiveCfg = Debug|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Debug|x64.Build.0 = Debug|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Debug|x86.ActiveCfg = Debug|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Debug|x86.Build.0 = Debug|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Release|Any CPU.Build.0 = Release|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Release|x64.ActiveCfg = Release|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Release|x64.Build.0 = Release|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Release|x86.ActiveCfg = Release|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Release|x86.Build.0 = Release|Any CPU
{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -115,4 +76,16 @@ Global
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x86.ActiveCfg = Release|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5} = {E959F9B5-F3EB-48B1-B842-2CDDFDB01900}
{F822B528-95FD-40B4-9EE0-3AE8878075AC} = {E959F9B5-F3EB-48B1-B842-2CDDFDB01900}
{BD9B8108-6528-430F-AD28-6F8434A29F55} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F4A8B63E-6284-4D00-9719-BAB1D955DACF}
EndGlobalSection
EndGlobal

@ -1,8 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
@ -13,4 +12,8 @@
<ProjectReference Include="..\..\src\DotXxlJob.Core\DotXxlJob.Core.csproj" />
</ItemGroup>
<ItemGroup>
<_ContentIncludedByDefault Remove="Properties\launchSettings.json" />
</ItemGroup>
</Project>

@ -1,27 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:22613",
"sslPort": 44333
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ASPNetCoreExecutor": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using DotXxlJob.Core;
@ -28,11 +29,21 @@ namespace ASPNetCoreExecutor
if ("POST".Equals(context.Request.Method, StringComparison.OrdinalIgnoreCase) &&
"application/octet-stream".Equals(context.Request.ContentType, StringComparison.OrdinalIgnoreCase))
{
/*
using (Stream file = File.Create("./"+DateTime.Now.ToUnixTimeSeconds()+".data"))
{
context.Request.Body.CopyTo(file);
}
return;
*/
var rsp = await _rpcService.HandlerAsync(context.Request.Body);
context.Response.StatusCode = (int) HttpStatusCode.OK;
context.Response.ContentType = "text/plain;utf-8";
await context.Response.Body.WriteAsync(rsp,0,rsp.Length);
return;
}
await _next.Invoke(context);

@ -6,21 +6,16 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\DotXxlJob.Core\DotXxlJob.Core.csproj" />
<ProjectReference Include="..\..\src\Hessian\Hessian.csproj" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
</ItemGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
<HintPath>C:\Program Files\dotnet\sdk\NuGetFallbackFolder\newtonsoft.json\11.0.2\lib\netstandard2.0\Newtonsoft.Json.dll</HintPath>
</Reference>
<ProjectReference Include="..\..\src\DotXxlJob.Core\DotXxlJob.Core.csproj" />
<ProjectReference Include="..\..\src\Hessian\Hessian.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="1547620263.dat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="1547621183.dat">
<None Update="run.dat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

@ -1,8 +1,9 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using DotXxlJob.Core;
using DotXxlJob.Core.Model;
using Hessian.Net;
using Hessian;
using Newtonsoft.Json;
namespace HessianReader
@ -11,7 +12,7 @@ namespace HessianReader
{
static void Main(string[] args)
{
byte[] myBinary = File.ReadAllBytes("1547621183.dat");
byte[] myBinary = File.ReadAllBytes("log.dat");
foreach (var i in myBinary)
{
@ -21,39 +22,32 @@ namespace HessianReader
}
Console.WriteLine(Environment.NewLine);
Console.WriteLine("---------------------------------------------------------------");
Console.WriteLine("---------------------{0}------------------------------------------",myBinary.Length);
var serializer = new DataContractHessianSerializer(typeof (RpcRequest));
using (var stream1 = new MemoryStream(myBinary))
{
var s = new Hessian.Deserializer(stream1);
var a = s.ReadValue();
Console.WriteLine(a);
a = s.ReadValue();
Console.WriteLine(a);
Console.WriteLine(JsonConvert.SerializeObject(a));
a = s.ReadValue();
Console.WriteLine(a);
Console.WriteLine(JsonConvert.SerializeObject(a));
a = s.ReadValue();
Console.WriteLine(a);
Console.WriteLine(JsonConvert.SerializeObject(a));
var s1 = HessianSerializer.DeserializeRequest(stream1);
Console.WriteLine(JsonConvert.SerializeObject(s1));
}
Console.WriteLine("------------------------------------------------------------");
Console.ReadKey();
return;
/**
*
* Console.WriteLine("---------------------------------------------------------------");
RpcRequest req = new RpcRequest {
RequestId = "71565f61-94e8-4dcf-9760-f2fb73a6886a",
CreateMillisTime = 1547621183585,
AccessToken = "",
ClassName = "com.xxl.job.core.biz.ExecutorBiz",
MethodName = "run",
ParameterTypes = new HessianArrayList {"class com.xxl.job.core.biz.model.TriggerParam"},
Version = "null",
Parameters = new HessianArrayList()
ParameterTypes = new List<object> {new JavaClass{ Name = "com.xxl.job.core.biz.model.TriggerParam"}},
Version = null,
Parameters = new List<object>()
};
var p =new TriggerParam {
@ -71,37 +65,25 @@ namespace HessianReader
BroadcastTotal=1
};
req.Parameters.Add(p);
byte[] distArray;
using (MemoryStream stream = new MemoryStream())
{
serializer.WriteObject(stream,req);
//Console.WriteLine(Environment.NewLine);
//Console.WriteLine("---------------------------"+ stream.Length+"------------------------------------");
stream.Flush();
distArray =stream.ToArray();
}
foreach (var j in distArray)
using (var stream2 = new MemoryStream())
{
Console.Write("0x");
Console.Write(j.ToString("x2"));
Console.Write(",");
var serializer = new Serializer(stream2);
serializer.WriteObject(req);
Console.WriteLine("-----------------------------序列化成功---{0}-------------------------------",stream2.Length);
stream2.Position = 0;
var s2 = HessianSerializer.DeserializeRequest(stream2);
Console.WriteLine(JsonConvert.SerializeObject(s2));
}
Console.WriteLine(Environment.NewLine);
Console.WriteLine("---------------------------------------------------------------");
using (var stream2 = new MemoryStream(distArray))
{
var instance = serializer.ReadObject(stream2) as RpcRequest;
* [{"Item1":"requestId","Item2":"71565f61-94e8-4dcf-9760-f2fb73a6886a"},{"Item1":"createMillisTime","Item2":1432957289},{"Item1":"accessToken","Item2":""},{"Item1":"className","Item2":"com.xxl.job.core.biz.ExecutorBiz"},{"Item1":"methodName","Item2":"run"},{"Item1":"version","Item2":null},{"Item1":"parameterT
ypes","Item2":[{"Name":"java.lang.Class","Fields":["name"]}]},{"Item1":"parameters","Item2":[{"Item1":"name","Item2":"com.xxl.job.core.biz.model.TriggerParam"}]}]
System.Collections.Generic.List`1[System.Object]
[{"Name":"com.xxl.job.core.biz.model.TriggerParam","Fields":["jobId","executorHandler","executorParams","executorBlockStrategy","executorTimeout","logId","logDateTim","glueType","glueSource","glueUpdatetime","broadcastIndex","broadcastTotal"]}]
Hessian.HessianObject
[{"Item1":"jobId","Item2":1},{"Item1":"executorHandler","Item2":"demoJobHandler"},{"Item1":"executorParams","Item2":"111"},{"Item1":"executorBlockStrategy","Item2":"SERIAL_EXECUTION"},{"Item1":"executorTimeout","Item2":0},{"Item1":"logId","Item2":5},{"Item1":"logDateTim","Item2":1432956926},{"Item1":"glueTy
pe","Item2":"BEAN"},{"Item1":"glueSource","Item2":""},{"Item1":"glueUpdatetime","Item2":-638368258},{"Item1":"broadcastIndex","Item2":0},{"Item1":"broadcastTotal","Item2":1}]
Console.WriteLine(JsonConvert.SerializeObject(instance));
}
/**
* requestId='71565f61-94e8-4dcf-9760-f2fb73a6886a',
* createMillisTime=1547621183585,
* accessToken='',

Binary file not shown.

Binary file not shown.

@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using DotXxlJob.Core.Config;
using DotXxlJob.Core.Model;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace DotXxlJob.Core
{
public class AdminClient
{
static readonly string MAPPING = "/api";
private readonly XxlJobExecutorOptions _options;
private readonly IHttpClientFactory _clientFactory;
private readonly ILogger<AdminClient> _logger;
private List<AddressEntry> _addresses;
private int _currentIndex;
public AdminClient(IOptions<XxlJobExecutorOptions> optionsAccessor
,IHttpClientFactory clientFactory
,ILogger<AdminClient> logger)
{
this._options = optionsAccessor.Value;
_clientFactory = clientFactory;
this._logger = logger;
InitAddress();
}
private void InitAddress()
{
this._addresses = new List<AddressEntry>();
foreach (var item in this._options.AdminAddresses)
{
try
{
var uri = new Uri(item + MAPPING);
var entry = new AddressEntry { RequestUri = uri };
this._addresses.Add(entry);
}
catch (Exception ex)
{
this._logger.LogError(ex, "init admin address error.");
}
}
}
public Task<ReturnT> Callback(List<HandleCallbackParam> callbackParamList)
{
return InvokeRpcService("callback", new List<string> {"java.util.List"}, callbackParamList);
}
public Task<ReturnT> Registry(RegistryParam registryParam)
{
return InvokeRpcService("callback", new List<string> {"java.lang.Class"}, registryParam);
}
public Task<ReturnT> RegistryRemove(RegistryParam registryParam)
{
return InvokeRpcService("callback", new List<string> {"java.lang.Class"}, registryParam);
}
private async Task<ReturnT> InvokeRpcService(string methodName, List<string> parameterTypes,
object parameters)
{
var request = new RpcRequest {
CreateMillisTime = DateTime.Now.ToUnixTimeSeconds(),
AccessToken = this._options.AccessToken,
ClassName = "com.xxl.job.core.biz.AdminBiz",
MethodName = methodName,
ParameterTypes = parameterTypes.ToList<object>(),
Parameters = new List<object> {parameters}
};
byte[] postBuf;
using (var stream = new MemoryStream())
{
HessianSerializer.SerializeRequest(stream,request);
postBuf =stream.ToArray();
}
int triedTimes = 0;
using (var client = this._clientFactory.CreateClient())
{
while (triedTimes++ < _addresses.Count)
{
var address = _addresses[_currentIndex];
_currentIndex = (_currentIndex + 1) % _addresses.Count;
if (!address.CheckAccessable())
continue;
Stream resStream;
try
{
resStream =await DoPost(client, address, postBuf);
address.Reset();
}
catch (Exception ex)
{
_logger.LogError(ex, "request admin error.");
address.SetFail();
continue;
}
RpcResponse res;
try
{
res = HessianSerializer.DeserializeResponse(resStream);
}
catch (Exception ex)
{
_logger.LogError("des");
}
if (res.IsError)
{
throw new Exception(res.error);
}
else
{
return rpcResponse.result as ReturnT;
}
}
}
throw new Exception("xxl-rpc server address not accessable.");
}
private async Task<Stream> DoPost(HttpClient client,AddressEntry address, byte[] postBuf)
{
var content = new ByteArrayContent(postBuf);
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
var responseMessage = await client.PostAsync(address.RequestUri, content);
responseMessage.EnsureSuccessStatusCode();
return await responseMessage.Content.ReadAsStreamAsync();
}
}
}

@ -6,7 +6,8 @@ namespace DotXxlJob.Core
{
public void Push(CallbackParam callbackParam)
{
throw new System.NotImplementedException();
//throw new System.NotImplementedException();
}
}
}

@ -4,6 +4,8 @@ namespace DotXxlJob.Core
{
internal static class Constants
{
public const string RpcRequestJavaFullName = "com.xxl.rpc.remoting.net.params.XxlRpcRequest";
public const string XxlLogsDefaultRootDirectory = "xxl-job-logs";
public const string HandleLogsDirectory = "HandlerLogs";
public const string LogFileNameCallContextKey = "XxlJob.LogFileName";

@ -6,10 +6,11 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Hessian.NET\Hessian.NET.csproj" />
<ProjectReference Include="..\Hessian\Hessian.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,193 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Runtime.Serialization;
using DotXxlJob.Core.Model;
using Hessian;
namespace DotXxlJob.Core
{
public static class HessianSerializer
{
private static readonly Dictionary<string, PropertyInfo> requestProperties =
new Dictionary<string, PropertyInfo>();
private static readonly Dictionary<string, PropertyInfo> triggerProperties =
new Dictionary<string, PropertyInfo>();
static HessianSerializer()
{
var typeInfo = typeof(RpcRequest).GetTypeInfo();
foreach (var property in typeInfo.DeclaredProperties)
{
var attribute = property.GetCustomAttribute<DataMemberAttribute>();
if (null == attribute)
{
continue;
}
if (!property.CanRead || !property.CanWrite)
{
continue;
}
requestProperties.Add(attribute.Name,property);
}
var triggerTypeInfo = typeof(TriggerParam).GetTypeInfo();
foreach (var property in triggerTypeInfo.DeclaredProperties)
{
var attribute = property.GetCustomAttribute<DataMemberAttribute>();
if (null == attribute)
{
continue;
}
if (!property.CanRead || !property.CanWrite)
{
continue;
}
triggerProperties.Add(attribute.Name,property);
}
}
public static RpcRequest DeserializeRequest(Stream stream)
{
RpcRequest request = new RpcRequest();
try
{
var deserializer = new Deserializer(stream);
var classDef = deserializer.ReadValue() as ClassDef;
if (!Constants.RpcRequestJavaFullName.Equals(classDef.Name))
{
throw new HessianException($"unknown class :{classDef.Name}");
}
if (requestProperties.Count != classDef.Fields.Length)
{
throw new HessianException($"unknown class :{classDef.Name}, field count not match ${requestProperties.Count} !={classDef.Fields.Length}");
}
//obj serialize
if (deserializer.ReadValue() is HessianObject hessianObject)
{
foreach (var item in hessianObject)
{
if (requestProperties.TryGetValue(item.Item1, out var p))
{
if (IsSimpleType(p.PropertyType.GetTypeInfo()))
{
p.SetValue(request,item.Item2);
}
else
{
if (item.Item2 is HessianObject )
{
request.Parameters = new List<object>();
var defList = deserializer.ReadValue() as List<object>;
foreach (var li in defList)
{
ReadParameters(deserializer,request.Parameters, li);
}
}
else
{
throw new HessianException($"unknown item :{item.Item1}");
}
}
}
}
}
}
catch (EndOfStreamException)
{
//没有数据可读了
}
return request;
}
private static void ReadParameters(Deserializer deserializer,IList<object> list, object item)
{
var itemType = item.GetType();
if (IsSimpleType(itemType.GetTypeInfo()))
{
list.Add(item);
return;
}
if (itemType == typeof(ClassDef))
{
var triggerClass = item as ClassDef;
//TODO:这里要做成动态的话 ,可以注册所有的实体到对应的字典中,不过这里只有这个类型哦
if (triggerClass.Name != "com.xxl.job.core.biz.model.TriggerParam")
{
throw new HessianException($"not expected parameter type [{triggerClass.Name}]");
}
if (!(deserializer.ReadValue() is HessianObject triggerData))
{
throw new HessianException("not expected parameter type ,data is null");
}
TriggerParam param = new TriggerParam();
foreach (var field in triggerData)
{
if (triggerProperties.TryGetValue(field.Item1, out var tgPropertyInfo))
{
tgPropertyInfo.SetValue(param,field.Item2);
}
}
}
else
{
throw new HessianException($"unsupported list item type =[{itemType}]");
}
}
public static void SerializeRequest(Stream stream,RpcRequest req)
{
var serializer = new Serializer(stream);
serializer.WriteObject(req);
}
public static void SerializeResponse(Stream stream,RpcResponse res)
{
var serializer = new Serializer(stream);
serializer.WriteObject(res);
}
private static bool IsSimpleType(TypeInfo typeInfo)
{
if (typeInfo.IsValueType || typeInfo.IsEnum || typeInfo.IsPrimitive)
{
return true;
}
if (typeof (String) == typeInfo.AsType())
{
return true;
}
return false;
}
public static RpcResponse DeserializeResponse(Stream resStream)
{
}
}
}

@ -110,7 +110,7 @@ namespace DotXxlJob.Core
JobQueue jobQueue = new JobQueue ( executor, this._callbackTaskQueue,this._jobQueueLogger);
if (RUNNING_QUEUE.TryAdd(triggerParam.JobId, jobQueue))
{
jobQueue.Push(triggerParam);
return jobQueue.Push(triggerParam);
}
return ReturnT.Failed("add running queue executor error");
}

@ -0,0 +1,39 @@
using System;
namespace DotXxlJob.Core.Model
{
public class AddressEntry
{
public Uri RequestUri { get; set; }
private DateTime? LastFailedTime { get; set; }
private int FailedTimes { get; set; }
public bool CheckAccessable()
{
if (LastFailedTime == null)
return true;
if (DateTime.UtcNow.Subtract(LastFailedTime.Value) > Constants.AdminServerReconnectInterval)
return true;
if (FailedTimes < Constants.AdminServerCircuitFaildTimes)
return true;
return false;
}
public void Reset()
{
LastFailedTime = null;
FailedTimes = 0;
}
public void SetFail()
{
LastFailedTime = DateTime.UtcNow;
FailedTimes++;
}
}
}

@ -0,0 +1,17 @@
using System.Runtime.Serialization;
namespace DotXxlJob.Core.Model
{
[DataContract(Name = "com.xxl.job.core.biz.model.HandleCallbackParam")]
public class HandleCallbackParam
{
[DataMember(Name = "callbackRetryTimes",Order = 1)]
public int CallbackRetryTimes;
[DataMember(Name = "logId",Order = 2)]
public int LogId;
[DataMember(Name = "logDateTim",Order = 3)]
public long LogDateTim;
[DataMember(Name = "executeResult",Order = 4)]
public ReturnT ExecuteResult;
}
}

@ -1,11 +0,0 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace DotXxlJob.Core.Model
{
[DataContract(Name = "hessianArrayList")]
public class HessianArrayList:List<object>
{
}
}

@ -0,0 +1,11 @@
using System.Runtime.Serialization;
namespace DotXxlJob.Core.Model
{
[DataContract(Name = "java.lang.Class")]
public class JavaClass
{
[DataMember(Name = "name",Order = 1)]
public string Name { get; set; }
}
}

@ -0,0 +1,17 @@
using System.Runtime.Serialization;
namespace DotXxlJob.Core.Model
{
[DataContract(Name = "com.xxl.job.core.biz.model.LogResult")]
public class LogResult
{
[DataMember(Name = "fromLineNum",Order = 1)]
public int FromLineNum { get; set; }
[DataMember(Name = "toLineNum",Order = 2)]
public int ToLineNum { get; set; }
[DataMember(Name = "logContent",Order = 3)]
public string LogContent { get; set; }
[DataMember(Name = "isEnd",Order = 4)]
public bool IsEnd { get; set; }
}
}

@ -0,0 +1,16 @@
using System.Runtime.Serialization;
namespace DotXxlJob.Core.Model
{
[DataContract(Name = "")]
public class RegistryParam
{
[DataMember(Name = "registGroup",Order = 1)]
public string RegistryGroup { get; set; }
[DataMember(Name = "registryKey",Order = 2)]
public string RegistryKey { get; set; }
[DataMember(Name = "registryValue",Order = 3)]
public string RegistryValue { get; set; }
}
}

@ -2,7 +2,7 @@ using System.Runtime.Serialization;
namespace DotXxlJob.Core
{
[DataContract]
[DataContract(Name = "com.xxl.job.core.biz.model.ReturnT")]
public class ReturnT
{
public const int SUCCESS_CODE = 200;
@ -12,11 +12,6 @@ namespace DotXxlJob.Core
public static readonly ReturnT FAIL = new ReturnT(FAIL_CODE, null);
public static readonly ReturnT FAIL_TIMEOUT = new ReturnT(502, null);
[DataMember(Name = "code",Order = 1)]
public int Code { get; set; }
[DataMember(Name = "msg",Order = 2)]
public string Msg { get; set; }
public ReturnT() { }
public ReturnT(int code, string msg)
@ -24,6 +19,17 @@ namespace DotXxlJob.Core
this.Code = code;
this.Msg = msg;
}
[DataMember(Name = "code",Order = 1)]
public int Code { get; set; }
[DataMember(Name = "msg",Order = 2)]
public string Msg { get; set; }
[DataMember(Name = "content",Order = 3)]
public object Content { get; set; }
public static ReturnT Failed(string msg)
{
@ -33,8 +39,7 @@ namespace DotXxlJob.Core
{
return new ReturnT(SUCCESS_CODE, msg);
}
[DataMember(Name = "content",Order = 3)]
public object Content { get; set; }
}

@ -1,5 +1,4 @@
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace DotXxlJob.Core.Model
@ -40,11 +39,11 @@ namespace DotXxlJob.Core.Model
public string Version{ get; set; }
[DataMember(Name = "parameterTypes",Order = 7)]
public HessianArrayList ParameterTypes{ get; set; }
public IList<object> ParameterTypes{ get; set; }
[DataMember(Name = "parameters",Order = 8)]
public HessianArrayList Parameters{ get; set; }
public IList<object> Parameters{ get; set; }
}

@ -3,43 +3,43 @@ using System.Runtime.Serialization;
namespace DotXxlJob.Core.Model
{
[DataContract(Name = "triggerParam")]
[DataContract(Name = "com.xxl.job.core.biz.model.TriggerParam")]
public class TriggerParam
{
static readonly long SerialVersionUID = 42L;
[DataMember(Name = "jobId")]
[DataMember(Name = "jobId",Order = 1)]
public int JobId { get; set; }
[DataMember(Name = "executorHandler")]
[DataMember(Name = "executorHandler",Order = 2)]
public string ExecutorHandler { get; set; }
[DataMember(Name = "executorParams")]
[DataMember(Name = "executorParams",Order = 3)]
public string ExecutorParams{ get; set; }
[DataMember(Name = "executorBlockStrategy")]
[DataMember(Name = "executorBlockStrategy",Order = 4)]
public string ExecutorBlockStrategy{ get; set; }
[DataMember(Name = "executorTimeout")]
[DataMember(Name = "executorTimeout",Order = 5)]
public int ExecutorTimeout{ get; set; }
[DataMember(Name = "logId")]
[DataMember(Name = "logId",Order = 5)]
public int LogId{ get; set; }
[DataMember(Name = "logDateTim")]
[DataMember(Name = "logDateTim",Order = 6)]
public long LogDateTime{ get; set; }
[DataMember(Name = "glueType")]
[DataMember(Name = "glueType",Order = 7)]
public string GlueType{ get; set; }
[DataMember(Name = "glueSource")]
[DataMember(Name = "glueSource",Order = 8)]
public string GlueSource{ get; set; }
[DataMember(Name = "glueUpdatetime")]
[DataMember(Name = "glueUpdatetime",Order = 9)]
public long GlueUpdateTime{ get; set; }
[DataMember(Name = "broadcastIndex")]
[DataMember(Name = "broadcastIndex",Order = 10)]
public int BroadcastIndex{ get; set; }
[DataMember(Name = "broadcastTotal")]
[DataMember(Name = "broadcastTotal",Order = 11)]
public int BroadcastTotal{ get; set; }
}
}

@ -12,6 +12,7 @@ namespace DotXxlJob.Core
services.AddSingleton<TaskExecutorFactory>();
services.AddSingleton<XxlRpcServiceHandler>();
services.AddSingleton<CallbackTaskQueue>();
services.AddSingleton<AdminClient>();
services.AddSingleton<IExecutorRegistry, ExecutorRegistry>();
return services;

@ -53,7 +53,6 @@ namespace DotXxlJob.Core
this._cancellationTokenSource?.Cancel();
this._cancellationTokenSource?.Dispose();
this._cancellationTokenSource = null;
}

@ -1,11 +1,11 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using DotXxlJob.Core.Config;
using DotXxlJob.Core.Model;
using Hessian.Net;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -20,8 +20,6 @@ namespace DotXxlJob.Core
private readonly JobDispatcher _jobDispatcher;
private readonly ILogger<XxlRpcServiceHandler> _logger;
private readonly DataContractHessianSerializer _reqSerializer;
private readonly DataContractHessianSerializer _resSerializer;
private readonly XxlJobExecutorOptions _options;
private readonly ConcurrentDictionary<string, MethodInfo> METHOD_CACHE =
@ -34,8 +32,7 @@ namespace DotXxlJob.Core
_jobDispatcher = jobDispatcher;
this._logger = logger;
this._reqSerializer = new DataContractHessianSerializer(typeof (RpcRequest));
this._resSerializer = new DataContractHessianSerializer(typeof (RpcResponse));
this._options = optionsAccessor.Value;
if (this._options == null)
{
@ -52,13 +49,10 @@ namespace DotXxlJob.Core
/// <exception cref="NotImplementedException"></exception>
public async Task<byte[]> HandlerAsync(Stream reqStream)
{
using (Stream output = File.OpenWrite(DateTime.Now.ToUnixTimeSeconds()+".dat"))
{
reqStream.CopyTo(output);
}
var req = _reqSerializer.ReadObject(reqStream) as RpcRequest;
var res = new RpcResponse();
var req = HessianSerializer.DeserializeRequest(reqStream);
var res = new RpcResponse { RequestId = req.RequestId};
if (!ValidRequest(req, out var error))
{
res.ErrorMsg = error;
@ -70,7 +64,7 @@ namespace DotXxlJob.Core
using (var outputStream = new MemoryStream())
{
_resSerializer.WriteObject(outputStream,res);
HessianSerializer.SerializeResponse(outputStream,res);
return outputStream.GetBuffer();
}
@ -192,6 +186,7 @@ namespace DotXxlJob.Core
private ReturnT Log(long logDateTime, int logId, int fromLineNum)
{
//var logResult = JobLogger.ReadLog(logDateTime, logId, fromLineNum);
Console.WriteLine("{0} ---{1} --{2}",logDateTime,logId,fromLineNum);
return ReturnT.Success(null);
}

@ -13,7 +13,7 @@ namespace Hessian.Net
public bool IsInstanceReference => ObjectPreamble.InstanceReference == preamble;
protected LeadingByte LeadingByte
public LeadingByte LeadingByte
{
get;
}
@ -355,11 +355,16 @@ namespace Hessian.Net
return ReadInt32();
}
public byte Peek()
{
byte value= (byte)this.Stream.ReadByte();
this.Stream.Position--;
return value;
}
public byte ReadByte()
{
return (byte)Stream.ReadByte();
return (byte)this.Stream.ReadByte();
}
protected void ReadLeadingByte()
{
var data = Stream.ReadByte();

@ -62,9 +62,7 @@ namespace Hessian.Net
private static ISerializationElement BuildSerializationObject(Type type, IDictionary<Type, ISerializationElement> catalog, IObjectSerializerFactory factory)
{
ISerializationElement existing;
if (catalog.TryGetValue(type, out existing))
if (catalog.TryGetValue(type, out var existing))
{
return existing;
}
@ -121,7 +119,7 @@ namespace Hessian.Net
return false;
}
public static bool IsListType(TypeInfo typeInfo)
private static bool IsListType(TypeInfo typeInfo)
{
return typeof(IEnumerable).IsAssignableFrom(typeInfo);
}

@ -59,9 +59,7 @@ namespace Hessian.Net
private string ReadTypeName(HessianInputReader reader)
{
var tag = reader.ReadByte();
var tag = reader.Peek();
// A type name is either a string, or an integer reference to a
// string already read and stored in the type-name ref map.
@ -74,22 +72,21 @@ namespace Hessian.Net
return typeName;
}
throw new HessianSerializerException();
reader.ReadInt32();
return "";
}
#region List
private IList<object> ReadVarList(HessianInputReader reader, HessianSerializationContext context)
{
reader.ReadByte();
var type = ReadTypeName(reader);
return ReadListCore(reader, context, type: type);
}
private IList<object> ReadFixList(HessianInputReader reader, HessianSerializationContext context)
{
reader.ReadByte();
var type = ReadTypeName(reader);
var length = reader.ReadInt32();
return ReadListCore(reader, context, length, type);
@ -97,20 +94,18 @@ namespace Hessian.Net
private IList<object> ReadVarListUntyped(HessianInputReader reader, HessianSerializationContext context)
{
reader.ReadByte();
return ReadListCore(reader, context);
}
private IList<object> ReadFixListUntyped(HessianInputReader reader, HessianSerializationContext context)
{
reader.ReadByte();
var length = reader.ReadInt32();
return ReadListCore(reader, context, length);
}
private IList<object> ReadCompactFixList(HessianInputReader reader, HessianSerializationContext context)
{
var tag = reader.ReadByte();
var tag = reader.LeadingByte.Data;
var length = tag - 0x70;
var type = ReadTypeName(reader);
return ReadListCore(reader, context, length, type);
@ -118,14 +113,14 @@ namespace Hessian.Net
private IList<object> ReadCompactFixListUntyped(HessianInputReader reader, HessianSerializationContext context)
{
var tag = reader.ReadByte();
var tag = reader.LeadingByte.Data;
var length = tag - 0x70;
return ReadListCore(reader, context, length);
}
private IList<object> ReadListCore(HessianInputReader reader, HessianSerializationContext context, int? length = null, string type = null)
{
var list = GetListIntance(type, length);
var list = GetListInstance(type, length);
//objectRefs.Add(list);
@ -137,7 +132,7 @@ namespace Hessian.Net
return list;
}
private IList<object> GetListIntance(string type, int? length = null)
private IList<object> GetListInstance(string type, int? length = null)
{
IList<object> list;
@ -156,9 +151,14 @@ namespace Hessian.Net
private void PopulateFixLengthList(HessianInputReader reader, HessianSerializationContext context, IList<object> list, int length)
{
for (var i = 0; i < length; ++i) {
//ObjectElement objectElement = new ObjectElement()
list.Add(this.ChildSerializationElement.Deserialize(reader,context));
var tag = reader.ReadByte(); //0x16
for (var i = 0; i < length; ++i)
{
ObjectElement objectElement = new ObjectElement();
var scheme = HessianSerializationScheme.CreateFromType(this.GetType(), this._factory);
var obj = scheme.Deserialize(reader, context);
list.Add(obj);
}
}

@ -101,12 +101,12 @@ namespace Hessian.Net
if (!String.Equals(ClassName, className))
if (!String.Equals(this.ClassName, className))
{
throw new HessianSerializerException();
}
if (ObjectProperties.Count != propertiesCount)
if (this.ObjectProperties.Count != propertiesCount)
{
throw new HessianSerializerException();
}
@ -114,8 +114,8 @@ namespace Hessian.Net
for (var index = 0; index < propertiesCount; index++)
{
var propertyName = reader.ReadString();
Console.WriteLine(propertyName);
var exists = ObjectProperties.Any(property => String.Equals(property.PropertyName, propertyName));
var exists = this.ObjectProperties.Any(property => String.Equals(property.PropertyName, propertyName));
if (!exists)
{
@ -123,7 +123,7 @@ namespace Hessian.Net
}
}
context.Classes.Add(ObjectType);
context.Classes.Add(this.ObjectType);
reader.EndClassDefinition();
}
@ -134,11 +134,10 @@ namespace Hessian.Net
}
var number = reader.ReadObjectReference();
var instance = Activator.CreateInstance(ObjectType);
var instance = Activator.CreateInstance(this.ObjectType);
context.Instances.Add(instance);
Console.WriteLine("===========================================");
foreach (var item in ObjectProperties)
foreach (var item in this.ObjectProperties)
{
Console.WriteLine(item.PropertyName);
var value = item.Deserialize(reader, context);

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace Hessian
{
public class ClassElement
{
public string ClassName { get; set; }
public List<PropertyElement> Fields { get; set; }
}
}

@ -0,0 +1,56 @@
using System;
namespace Hessian
{
/// <summary>
///
/// </summary>
internal static class DateTimeExtension
{
private const long Era = 62135596800000L;
private const long Millis = 60000;
/// <summary>
///
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static long GetTotalMilliseconds(this DateTime dt)
{
return dt.ToUniversalTime().Ticks / 10000 - Era;
}
/// <summary>
///
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static int GetTotalMinutes(this DateTime dt)
{
var val = GetTotalMilliseconds(dt);
return (int)(val / Millis);
}
/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static DateTime FromMinutes(int value)
{
var ticks = (value * Millis + Era) * 10000;
return new DateTime(ticks, DateTimeKind.Utc);
}
/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static DateTime FromMilliseconds(long value)
{
var ticks = (value + Era) * 10000;
return new DateTime(ticks, DateTimeKind.Utc);
}
}
}

@ -22,7 +22,7 @@ namespace Hessian
public Deserializer (Stream stream)
{
if (stream == null) {
throw new ArgumentNullException("stream");
throw new ArgumentNullException(nameof(stream));
}
reader = new ValueReader(stream);
@ -40,97 +40,127 @@ namespace Hessian
if (!tag.HasValue) {
throw new EndOfStreamException();
}
switch (tag.Value) {
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F:
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
return ReadShortString();
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F:
return ReadShortBinary();
case 0x30: case 0x31: case 0x32: case 0x33:
return ReadMediumString();
case 0x34: case 0x35: case 0x36: case 0x37:
return ReadMediumBinary();
case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F:
return ReadLongThreeBytes();
case 0x40:
return Reserved();
case 0x41: case 0x42:
return ReadChunkedBinary();
case 0x43:
return ReadClassDefinition();
case 0x44:
return ReadFullDouble();
case 0x45:
return Reserved();
case 0x46:
return ReadBoolean();
case 0x47:
return Reserved();
case 0x48:
return ReadUntypedMap();
case 0x49:
return ReadInteger();
case 0x4A:
return ReadDateInMillis();
case 0x4B:
return ReadDateInMinutes();
case 0x4C:
return ReadLongFull();
case 0x4D:
return ReadTypedMap();
case 0x4E:
return ReadNull();
case 0x4F:
return ReadObject();
case 0x50:
return Reserved();
case 0x51:
return ReadRef();
case 0x52: case 0x53:
return ReadChunkedString();
case 0x54:
return ReadBoolean();
case 0x55:
return ReadVarList();
case 0x56:
return ReadFixList();
case 0x57:
return ReadVarListUntyped();
case 0x58:
return ReadFixListUntyped();
case 0x59:
return ReadLongFourBytes();
case 0x5A:
@ -138,19 +168,24 @@ namespace Hessian
throw new UnexpectedTagException(0x5A, "value");
case 0x5B: case 0x5C:
return ReadDoubleOneByte();
case 0x5D:
return ReadDoubleOneByte();
case 0x5E:
return ReadDoubleTwoBytes();
case 0x5F:
return ReadDoubleFourBytes();
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F:
return ReadObjectCompact();
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
@ -171,9 +206,11 @@ namespace Hessian
case 0xC0: case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7:
case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
return ReadIntegerTwoBytes();
case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4: case 0xD5: case 0xD6: case 0xD7:
return ReadIntegerThreeBytes();
case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF:
@ -261,7 +298,7 @@ namespace Hessian
private IList<object> ReadListCore(int? length = null, string type = null)
{
var list = GetListIntance(type, length);
var list = GetListInstance(type, length);
objectRefs.Add(list);
@ -273,7 +310,7 @@ namespace Hessian
return list;
}
private IList<object> GetListIntance(string type, int? length = null)
private IList<object> GetListInstance(string type, int? length = null)
{
IList<object> list;
@ -700,10 +737,15 @@ namespace Hessian
private long ReadLongFull()
{
var data = new byte[9];
reader.Read(data, data.Length);
return LongFromBytes(data, 1);
}
private long ReadLongOneByte()
{
return reader.ReadByte() - 0xE0;
@ -865,6 +907,9 @@ namespace Hessian
if (tag != 0x51) {
throw new UnexpectedTagException(tag.Value, "ref");
}
reader.ReadByte();//过滤tag
return objectRefs.Get(ReadInteger());
}
@ -878,14 +923,29 @@ namespace Hessian
private static long LongFromBytes(byte[] buffer, int offset)
{
return (buffer[offset + 0] << 0x38)
| (buffer[offset + 1] << 0x30)
| (buffer[offset + 2] << 0x28)
| (buffer[offset + 3] << 0x20)
| (buffer[offset + 4] << 0x18)
| (buffer[offset + 5] << 0x10)
| (buffer[offset + 6] << 0x08)
| (buffer[offset + 7] << 0x00);
/*
var value = (long) reader.ReadByte() << 56;
value |= ((long) reader.ReadByte() << 48);
value |= ((long) reader.ReadByte() << 40);
value |= ((long) reader.ReadByte() << 32);
value |= ((long) reader.ReadByte() << 24);
value |= ((long) reader.ReadByte() << 16);
value |= ((long) reader.ReadByte() << 8);
value |= (uint)reader.ReadByte();
return value;
*/
return ((long)buffer[offset + 0] << 0x38)
+ ((long)buffer[offset + 1] << 0x30)
| ((long)buffer[offset + 2] << 0x28)
| ((long)buffer[offset + 3] << 0x20)
| ((long)buffer[offset + 4] << 0x18)
| ((long)buffer[offset + 5] << 0x10)
| ((long)buffer[offset + 6] << 0x08)
| ((uint)buffer[offset + 7] << 0x00);
}
}
}

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
</Project>

@ -10,20 +10,11 @@ namespace Hessian
private readonly string typeName;
private readonly IDictionary<string, object> fields;
public string TypeName
{
get { return typeName; }
}
public string TypeName => typeName;
public object this[string key]
{
get { return fields[key]; }
}
public object this[string key] => fields[key];
public int Count
{
get { return fields.Count; }
}
public int Count => fields.Count;
private HessianObject(string typeName)
{

@ -0,0 +1,27 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Hessian
{
public class HessianSerializationContext
{
public IList<Type> Classes
{
get;
private set;
}
public IList Instances
{
get;
private set;
}
public HessianSerializationContext()
{
Classes = new List<Type>();
Instances = new List<object>();
}
}
}

@ -1,24 +0,0 @@
using System;
using System.IO;
using System.Text;
namespace Hessian
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Hello World!");
var bytes = Encoding.UTF8.GetBytes("Hessian");
var ms = new MemoryStream();
ms.WriteByte((byte)"Hessian".Length);
ms.Write (bytes, 0, bytes.Length);
ms.Position = 0;
var ds = new Deserializer(ms);
var actual = ds.ReadValue();
Console.WriteLine(actual);
}
}
}

@ -0,0 +1,39 @@
namespace Hessian
{
internal static class Marker
{
public const byte True = (byte) 'T';//0x54;
public const byte False = (byte) 'F';// 0x46;
public const byte Null = (byte) 'N';//0x4E;
public const byte BinaryNonfinalChunk = (byte) 'b';//0x41;
public const byte BinaryFinalChunk = (byte) 'B';//0x42;
public const byte ClassDefinition = (byte) 'C';//0x43;
public const byte DateTimeLong = 0x4A;
public const byte DateTimeCompact = 0x4B;
public const byte Double = 0x5A;
public const byte DoubleZero = 0x5B;
public const byte DoubleOne = 0x5C;
public const byte DoubleOctet = 0x5D;
public const byte DoubleShort = 0x5E;
public const byte DoubleFloat = 0x5F;
public const byte UnpackedInteger = (byte) 'I';// 0x49;
public const byte PackedLong = (byte) 'Y';// 0x59;
public const byte UnpackedLong = (byte) 'L';// 0x4C;
public const byte StringNonfinalChunk = 0x52;
public const byte StringFinalChunk = 0x53;
public const byte VarList = 0x55;
public const byte FixedList = 0x56;
public const byte VarListUntyped = 0x57;
public const byte FixListUntyped = 0x58;
public const byte CompactFixListStart = 0x70;
public const byte CompactFixListEnd = 0x77;
public const byte CompactFixListUntypedStart = 0x78;
public const byte CompactFixListUntypedEnd = 0x7F;
public const byte ClassReference = (byte) 'O';//0x4F
public const byte InstanceReference = (byte) 'Q'; //0x51;
}
}

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Hessian
{
public class PropertyElement
{
public string Name { get; set; }
public int Order { get; set; }
public PropertyInfo PropertyInfo { get; set; }
}
internal class PropertyComparer : IComparer<PropertyElement>
{
private readonly IComparer<int> comparer;
public PropertyComparer()
{
comparer = Comparer<int>.Default;
}
public int Compare(PropertyElement x, PropertyElement y)
{
var eq = comparer.Compare(x.Order, y.Order);
return 0 == eq
? String.Compare(x.Name, y.Name, StringComparison.Ordinal)
: eq;
}
}
}

@ -0,0 +1,517 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
namespace Hessian
{
public class Serializer
{
static readonly ConcurrentDictionary<Type,ClassElement> ClassDefCache =new ConcurrentDictionary<Type, ClassElement>();
private readonly Stream _stream;
private readonly HessianSerializationContext _context;
public Serializer (Stream stream)
{
this._stream = stream ?? throw new ArgumentNullException(nameof(stream));
_context = new HessianSerializationContext();
}
public void WriteObject(object graph)
{
var objectType = graph.GetType();
if (!ClassDefCache.TryGetValue(objectType, out var classDef))
{
classDef = GetClassDef(objectType.GetTypeInfo());
}
var index = this._context.Instances.IndexOf(graph);
if (index > -1)
{
WriteInstanceReference(index);
return;
}
this._context.Instances.Add(graph);
index = this._context.Classes.IndexOf(objectType);
if (index < 0)
{
BeginClassDefinition();
WriteString(classDef.ClassName);
WriteInt32(classDef.Fields.Count);
foreach (var property in classDef.Fields)
{
WriteString(property.Name);
}
EndClassDefinition();
index = this._context.Classes.Count;
this._context.Classes.Add(objectType);
}
WriteObjectReference(index);
foreach (var item in classDef.Fields)
{
var value = item.PropertyInfo.GetValue(graph);
WriteValue(value);
}
}
public void WriteValue(object val)
{
if (val == null)
{
WriteNull();
return;
}
var valType = val.GetType();
var typeInfo = valType.GetTypeInfo();
if (IsSimpleType(typeInfo))
{
WriteSimpleValue(val);
return;
}
if (IsListType(typeInfo))
{
WriteListValue(val);
return;
}
WriteObject(val);
}
private void WriteListValue(object val)
{
var tag = (int)Marker.CompactFixListStart;
if (!(val is ICollection eVal))
{
throw new HessianException("write list data error");
}
tag += eVal.Count;
if (tag > Marker.CompactFixListEnd)
{
throw new HessianException("write list data error,tag too large");
}
this._stream.WriteByte((byte)tag);
int index = 1;
foreach (var item in eVal)
{
if (index == 1)
{
WriteString("["+GetItemTypeName(item.GetType()));
}
WriteValue(item);
}
}
private string GetItemTypeName(Type type)
{
var classType = type.GetCustomAttribute<DataContractAttribute>();
if (classType != null)
{
return classType.Name;
}
return type.Name;
}
private void WriteSimpleValue(object val)
{
var valType = val.GetType();
if (valType == typeof(int))
{
WriteInt32((int)val);
}
else if (valType == typeof(bool))
{
WriteBoolean((bool)val);
}
else if (valType == typeof(long))
{
WriteInt64((long)val);
}
else if (valType == typeof(double))
{
WriteDouble((double)val);
}
else if (valType == typeof(string))
{
WriteString((string)val);
}
else if (valType == typeof(DateTime))
{
WriteDateTime((DateTime)val);
}
}
private ClassElement GetClassDef(TypeInfo typeInfo)
{
var classAttr = typeInfo.GetCustomAttribute<DataContractAttribute>();
if (classAttr == null)
{
throw new HessianException("DataContract must be set");
}
ClassElement ce = new ClassElement {ClassName = classAttr.Name, Fields = new List<PropertyElement>()};
//ClassDef def = new ClassDef(classAttr.Name);
foreach (var property in typeInfo.DeclaredProperties)
{
var attribute = property.GetCustomAttribute<DataMemberAttribute>();
if (null == attribute)
{
continue;
}
if (!property.CanRead || !property.CanWrite)
{
continue;
}
PropertyElement p = new PropertyElement {
Name = attribute.Name,
Order = attribute.Order,
PropertyInfo = property
};
ce.Fields .Add( p );
}
ce.Fields.Sort(new PropertyComparer());
return ce;
}
/// <summary>
/// Writes NULL token into stream
/// </summary>
public void WriteNull()
{
this._stream.WriteByte(Marker.Null);
}
/// <summary>
/// Writes <see cref="System.Boolean" /> value into output stream.
/// </summary>
/// <param name="value">The value.</param>
public void WriteBoolean(bool value)
{
this._stream.WriteByte(value ? Marker.True : Marker.False);
}
/// <summary>
/// Writes array of <see cref="System.Byte" /> into output stream.
/// </summary>
/// <param name="buffer">The value.</param>
public void WriteBytes(byte[] buffer)
{
if (null == buffer)
{
WriteNull();
return;
}
WriteBytes(buffer, 0, buffer.Length);
}
public void WriteBytes(byte[] buffer, int offset, int count)
{
if (offset < 0)
{
throw new ArgumentException("", nameof(offset));
}
if (null == buffer)
{
WriteNull();
return;
}
if (count < 0x10)
{
this._stream.WriteByte((byte)(0x20 + (count & 0x0F)));
this._stream.Write(buffer, offset, count);
return;
}
const int chunkSize = 0x8000;
while (count > chunkSize)
{
this._stream.WriteByte(Marker.BinaryNonfinalChunk);
this._stream.WriteByte(chunkSize >> 8);
this._stream.WriteByte(chunkSize & 0xFF);
this._stream.Write(buffer, offset, chunkSize);
count -= chunkSize;
offset += chunkSize;
}
this._stream.WriteByte(Marker.BinaryFinalChunk);
this._stream.WriteByte((byte)(count >> 8));
this._stream.WriteByte((byte)(count & 0xFF));
this._stream.Write(buffer, offset, count);
}
public void WriteDateTime(DateTime value)
{
if (value.Second == 0)
{
var s = value.GetTotalMinutes();
this._stream.WriteByte(Marker.DateTimeCompact);
this._stream.WriteByte((byte)(s >> 24));
this._stream.WriteByte((byte)(s >> 16));
this._stream.WriteByte((byte)(s >> 8));
this._stream.WriteByte((byte)s);
return;
}
var dt = value.GetTotalMilliseconds();
this._stream.WriteByte(Marker.DateTimeLong);
this._stream.WriteByte((byte)(dt >> 56));
this._stream.WriteByte((byte)(dt >> 48));
this._stream.WriteByte((byte)(dt >> 40));
this._stream.WriteByte((byte)(dt >> 32));
this._stream.WriteByte((byte)(dt >> 24));
this._stream.WriteByte((byte)(dt >> 16));
this._stream.WriteByte((byte)(dt >> 8));
this._stream.WriteByte((byte)dt);
}
public void WriteDouble(double value)
{
if (value.Equals(0.0d))
{
this._stream.WriteByte(Marker.DoubleZero);
return;
}
if (value.Equals(1.0d))
{
this._stream.WriteByte(Marker.DoubleOne);
return;
}
var fraction = Math.Abs(value - Math.Truncate(value));
if (Double.Epsilon >= fraction)
{
if (Byte.MinValue <= value && value <= Byte.MaxValue)
{
this._stream.WriteByte(Marker.DoubleOctet);
this._stream.WriteByte(Convert.ToByte(value));
return;
}
if (Int16.MinValue <= value && value <= Int16.MaxValue)
{
var val = Convert.ToInt16(value);
this._stream.WriteByte(Marker.DoubleShort);
this._stream.WriteByte((byte)(val >> 8));
this._stream.WriteByte((byte)val);
return;
}
}
if (Single.MinValue <= value && value <= Single.MaxValue)
{
var bytes = BitConverter.GetBytes((float) value);
this._stream.WriteByte(Marker.DoubleFloat);
for (var index = bytes.Length - 1; index >= 0; index--)
{
this._stream.WriteByte(bytes[index]);
}
return;
}
var temp = BitConverter.DoubleToInt64Bits(value);
this._stream.WriteByte(Marker.Double);
for (var index = 56; index >= 0; index -= 8)
{
this._stream.WriteByte((byte) (temp >> index));
}
}
public void WriteInt32(int value)
{
if (-16 <= value && value < 48)
{
this._stream.WriteByte((byte)(0x90 + value));
}
else if (-2048 <= value && value < 2048)
{
this._stream.WriteByte((byte)(0xC8 + (byte)(value >> 8)));
this._stream.WriteByte((byte)value);
}
else if (-262144 <= value && value < 262144)
{
this._stream.WriteByte((byte)(0xD4 + (byte)(value >> 16)));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
else
{
this._stream.WriteByte(Marker.UnpackedInteger);
this._stream.WriteByte((byte)(value >> 24));
this._stream.WriteByte((byte)(value >> 16));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
}
public void WriteInt64(long value)
{
if (-8 <= value && value < 16)
{
this._stream.WriteByte((byte)(0xE0 + value));
}
else if (-2048 <= value && value < 2048)
{
this._stream.WriteByte((byte)(0xF8 + (byte)(value >> 8)));
this._stream.WriteByte((byte)value);
}
else if (-262144 <= value && value < 262144)
{
this._stream.WriteByte((byte)(0x3C + (byte)(value >> 16)));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
else if (Int32.MinValue <= value && value <= Int32.MaxValue)
{
this._stream.WriteByte(Marker.PackedLong);
this._stream.WriteByte((byte)(value >> 24));
this._stream.WriteByte((byte)(value >> 16));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
else
{
this._stream.WriteByte(Marker.UnpackedLong);
this._stream.WriteByte((byte)(value >> 56));
this._stream.WriteByte((byte)(value >> 48));
this._stream.WriteByte((byte)(value >> 40));
this._stream.WriteByte((byte)(value >> 32));
this._stream.WriteByte((byte)(value >> 24));
this._stream.WriteByte((byte)(value >> 16));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
}
public void WriteString(string value)
{
if (string.IsNullOrEmpty(value))
{
this._stream.WriteByte(0x00);
return;
}
var length = value.Length;
if (1024 > length)
{
var bytes = Encoding.UTF8.GetBytes(value.ToCharArray());
if (32 > length)
{
this._stream.WriteByte((byte) length);
}
else
{
this._stream.WriteByte((byte) (0x30 + (byte) (length >> 8)));
this._stream.WriteByte((byte) length);
}
this._stream.Write(bytes, 0, bytes.Length);
return;
}
const int maxChunkLength = 1024;
var position = 0;
while (position < length)
{
var count = Math.Min(length - position, maxChunkLength);
var final = length == (position + count);
var chunk = value.Substring(position, count);
var bytes = Encoding.UTF8.GetBytes(chunk.ToCharArray());
this._stream.WriteByte(final ? Marker.StringFinalChunk : Marker.StringNonfinalChunk);
this._stream.WriteByte((byte)(count >> 8));
this._stream.WriteByte((byte)count);
this._stream.Write(bytes, 0, bytes.Length);
position += count;
}
}
public void BeginClassDefinition()
{
this._stream.WriteByte(Marker.ClassDefinition);
}
public void EndClassDefinition()
{
}
public void WriteObjectReference(int index)
{
if (index < 0x10)
{
this._stream.WriteByte((byte)(0x60 + index));
}
else
{
this._stream.WriteByte(Marker.ClassReference);
WriteInt32(index);
}
}
public void WriteInstanceReference(int index)
{
this._stream.WriteByte(Marker.InstanceReference);
WriteInt32(index);
}
private static bool IsSimpleType(TypeInfo typeInfo)
{
if (typeInfo.IsValueType || typeInfo.IsEnum || typeInfo.IsPrimitive)
{
return true;
}
if (typeof (String) == typeInfo.AsType())
{
return true;
}
return false;
}
private static bool IsListType(TypeInfo typeInfo)
{
return typeof(ICollection).IsAssignableFrom(typeInfo);
}
}
}
Loading…
Cancel
Save