Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9a23c9b

Browse files
author
webmote
committed
重构thrift解码
1 parent 3d50996 commit 9a23c9b

File tree

6 files changed

+270
-3
lines changed

6 files changed

+270
-3
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp2.2</TargetFramework>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<PackageReference Include="apache-thrift-netcore" Version="0.9.3.2" />
8+
<PackageReference Include="DotNetty.Codecs" Version="0.6.0" />
9+
</ItemGroup>
10+
</Project>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright (c) CodeEx.cn & webmote. All rights reserved.
2+
// Licensed under theApache License.
3+
// See LICENSE file in the project root for full license information.
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Diagnostics.Contracts;
7+
using System.IO;
8+
using System.Text;
9+
using DotNetty.Buffers;
10+
using DotNetty.Transport.Channels;
11+
using Thrift.Protocol;
12+
using Thrift.Transport;
13+
14+
namespace DotNetty.Codecs.Thrift
15+
{
16+
/// <summary>
17+
/// 按照 TBinaryProtocol , 解析 Thrift 消息
18+
/// </summary>
19+
public class ThriftBinaryDecoder : MessageToMessageDecoder<IByteBuffer>
20+
{
21+
private ThriftOptions _opts;
22+
public ThriftBinaryDecoder(ThriftOptions options = null)
23+
{
24+
_opts = options ?? ThriftOptions.DefaultOptions;
25+
}
26+
protected override void Decode(IChannelHandlerContext context, IByteBuffer message, List<object> output)
27+
{
28+
Contract.Requires(context != null);
29+
Contract.Requires(message != null);
30+
Contract.Requires(output != null);
31+
32+
int length = message.ReadableBytes;
33+
if (length <= 0)
34+
{
35+
return;
36+
}
37+
38+
Stream inputStream = null;
39+
try
40+
{
41+
TBinaryProtocol protocol = new TBinaryProtocol(new TMemoryBufferClientTransport());
42+
if (message.IoBufferCount == 1)
43+
{
44+
ArraySegment<byte> bytes = message.GetIoBuffer(message.ReaderIndex, length);
45+
codedInputStream = CodedInputStream.CreateInstance(bytes.Array, bytes.Offset, length);
46+
}
47+
else
48+
{
49+
inputStream = new ReadOnlyByteBufferStream(message, false);
50+
codedInputStream = CodedInputStream.CreateInstance(inputStream);
51+
}
52+
53+
54+
IBuilderLite newBuilder = this.protoType.WeakCreateBuilderForType();
55+
IBuilderLite messageBuilder = this.extensionRegistry == null
56+
? newBuilder.WeakMergeFrom(codedInputStream)
57+
: newBuilder.WeakMergeFrom(codedInputStream, this.extensionRegistry);
58+
59+
IMessageLite decodedMessage = messageBuilder.WeakBuild();
60+
if (decodedMessage != null)
61+
{
62+
output.Add(decodedMessage);
63+
}
64+
}
65+
catch (Exception exception)
66+
{
67+
throw new CodecException(exception);
68+
}
69+
finally
70+
{
71+
inputStream?.Dispose();
72+
}
73+
}
74+
}
75+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright (c) CodeEx.cn & webmote. All rights reserved.
2+
// Licensed under theApache License.
3+
// See LICENSE file in the project root for full license information.
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Diagnostics.Contracts;
7+
using System.Text;
8+
using DotNetty.Buffers;
9+
using DotNetty.Transport.Channels;
10+
11+
namespace DotNetty.Codecs.Thrift
12+
{
13+
///
14+
/// A decoder that splits the received {@link ByteBuf}s dynamically by the
15+
/// value of the Thrift Frame Buffers
16+
/// Base 1 integer length field in the message.
17+
/// For example:
18+
///
19+
/// BEFORE DECODE (304 bytes) AFTER DECODE (300 bytes)
20+
/// +------------+---------------+ +---------------+
21+
/// | Length | Thrift Data |----->| Thrift Data |
22+
/// | 0x0000AC02 | (300 bytes) | | (300 bytes) |
23+
/// +------------+---------------+ +---------------+
24+
///
25+
public class ThriftFrameDecoder : ByteToMessageDecoder
26+
{
27+
private ThriftOptions _opts;
28+
// todo: maxFrameLength + safe skip + fail-fast option (just like LengthFieldBasedFrameDecoder)
29+
public ThriftFrameDecoder(ThriftOptions options = null)
30+
{
31+
_opts = options ?? ThriftOptions.DefaultOptions;
32+
}
33+
34+
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
35+
{
36+
input.MarkReaderIndex();
37+
38+
int preIndex = input.ReaderIndex;
39+
int length = ReadRawVarint32(input);
40+
41+
if (preIndex == input.ReaderIndex)
42+
{
43+
return;
44+
}
45+
46+
if (length < 0)
47+
{
48+
throw new CorruptedFrameException($"Negative length: {length}");
49+
}
50+
51+
if (input.ReadableBytes < length)
52+
{
53+
input.ResetReaderIndex();
54+
}
55+
else
56+
{
57+
if (length > _opts.MaxFrameSize)
58+
{
59+
input.SetReaderIndex(length);
60+
context.FireExceptionCaught(new TooLongFrameException($"frame length ({length}) exceeds the allowed maximum ({_opts.MaxFrameSize})"));
61+
}
62+
IByteBuffer byteBuffer = input.ReadSlice(length);
63+
output.Add(byteBuffer.Retain());
64+
}
65+
}
66+
67+
static int ReadRawVarint32(IByteBuffer buffer)
68+
{
69+
Contract.Requires(buffer != null);
70+
71+
if (!buffer.IsReadable())
72+
{
73+
return 0;
74+
}
75+
76+
buffer.MarkReaderIndex();
77+
if (buffer.ReadableBytes >= 4)
78+
{
79+
return buffer.ReadInt();
80+
}
81+
else
82+
{
83+
buffer.ResetReaderIndex();
84+
return 0;
85+
}
86+
}
87+
}
88+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) CodeEx.cn & webmote. All rights reserved.
2+
// Licensed under theApache License.
3+
// See LICENSE file in the project root for full license information.
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Text;
7+
8+
namespace DotNetty.Codecs.Thrift
9+
{
10+
/// <summary>
11+
/// 解析Thrift需设置的参数
12+
/// </summary>
13+
public class ThriftOptions
14+
{
15+
public static ThriftOptions DefaultOptions = new ThriftOptions();
16+
/// <summary>
17+
/// 解析数据时,最大递归深度 64
18+
/// </summary>
19+
public const int DefaultRecursionDepth = 64;
20+
//todo: 以后如果有变动
21+
public ThriftOptions(string thriftVersion = "0.9")
22+
{
23+
VERSION_MASK = 0xffff0000;
24+
VERSION_1 = 0x80010000;
25+
MaxFrameSize = 10240 * 1024; //10M
26+
StrictRead = false;
27+
StrictWrite = true;
28+
}
29+
/// <summary>
30+
/// 最大通讯字节限制
31+
/// </summary>
32+
public int MaxFrameSize { get; set; }
33+
/// <summary>
34+
/// 严格读
35+
/// </summary>
36+
public bool StrictRead { get; set; }
37+
/// <summary>
38+
/// 严格写
39+
/// </summary>
40+
public bool StrictWrite { get; set; }
41+
42+
/// <summary>
43+
/// 版本标识
44+
/// </summary>
45+
public readonly uint VERSION_1;
46+
47+
/// <summary>
48+
/// 版本掩码
49+
/// </summary>
50+
51+
public readonly uint VERSION_MASK;
52+
53+
54+
}
55+
}

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,35 @@
11
# DotNetty.Codecs.Thrift
22
DotNetty Codes Lib for Thrift
3+
4+
5+
About Apache Thrift
6+
============
7+
8+
Thrift is a lightweight, language-independent software stack with an
9+
associated code generation mechanism for point-to-point RPC. Thrift provides
10+
clean abstractions for data transport, data serialization, and application
11+
level processing. The code generation system takes a simple definition
12+
language as input and generates code across programming languages that
13+
uses the abstracted stack to build interoperable RPC clients and servers.
14+
15+
![Apache Thrift Layered Architecture](https://github.com/apache/thrift/raw/master/doc/images/thrift-layers.png)
16+
17+
Thrift makes it easy for programs written in different programming
18+
languages to share data and call remote procedures. With support
19+
for [25 programming languages](LANGUAGES.md), chances are Thrift
20+
supports the languages that you currently use.
21+
22+
Thrift is specifically designed to support non-atomic version changes
23+
across client and server code.
24+
25+
For more details on Thrift's design and implementation, see the Thrift
26+
whitepaper included in this distribution, or at the README.md file
27+
in your particular subdirectory of interest.
28+
29+
License
30+
======
31+
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
32+
33+
http://www.apache.org/licenses/LICENSE-2.0
34+
35+
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

ThriftForNetty.sln

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 16
4-
VisualStudioVersion = 16.0.28729.10
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.27703.2000
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThriftForNetty", "ThriftForNetty\ThriftForNetty.csproj", "{0E90DEB1-2DFC-4D23-BD91-BDAC2BC29F3D}"
77
EndProject
88
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThriftCodesLib", "ThriftCodesLib\ThriftCodesLib.csproj", "{4A0889B4-A2B8-4452-BACF-8594579AE8AD}"
99
EndProject
1010
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{FC346372-A74C-40EB-830B-44206EAE5C86}"
1111
EndProject
12-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftAnnotations", "ThriftAnnotations\ThriftAnnotations.csproj", "{75BC6937-313A-4C2B-A993-8B91F69EAE3B}"
12+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThriftAnnotations", "ThriftAnnotations\ThriftAnnotations.csproj", "{75BC6937-313A-4C2B-A993-8B91F69EAE3B}"
13+
EndProject
14+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetty.Codecs.Thrift", "DotNetty.Codecs.Thrift\DotNetty.Codecs.Thrift.csproj", "{70347D26-3423-4161-8336-B136106CC51A}"
1315
EndProject
1416
Global
1517
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -33,6 +35,10 @@ Global
3335
{75BC6937-313A-4C2B-A993-8B91F69EAE3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
3436
{75BC6937-313A-4C2B-A993-8B91F69EAE3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
3537
{75BC6937-313A-4C2B-A993-8B91F69EAE3B}.Release|Any CPU.Build.0 = Release|Any CPU
38+
{70347D26-3423-4161-8336-B136106CC51A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39+
{70347D26-3423-4161-8336-B136106CC51A}.Debug|Any CPU.Build.0 = Debug|Any CPU
40+
{70347D26-3423-4161-8336-B136106CC51A}.Release|Any CPU.ActiveCfg = Release|Any CPU
41+
{70347D26-3423-4161-8336-B136106CC51A}.Release|Any CPU.Build.0 = Release|Any CPU
3642
EndGlobalSection
3743
GlobalSection(SolutionProperties) = preSolution
3844
HideSolutionNode = FALSE

0 commit comments

Comments
 (0)