1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
using System;
using System.Collections.Generic;
namespace Org.BouncyCastle.Tls
{
internal sealed class DtlsReassembler
{
private readonly short m_msg_type;
private readonly byte[] m_body;
private readonly List<Range> m_missing = new List<Range>();
internal DtlsReassembler(short msg_type, int length)
{
this.m_msg_type = msg_type;
this.m_body = new byte[length];
this.m_missing.Add(new Range(0, length));
}
internal short MsgType
{
get { return m_msg_type; }
}
internal byte[] GetBodyIfComplete()
{
return m_missing.Count > 0 ? null : m_body;
}
internal void ContributeFragment(short msg_type, int length, byte[] buf, int off, int fragment_offset,
int fragment_length)
{
int fragment_end = fragment_offset + fragment_length;
if (m_msg_type != msg_type || m_body.Length != length || fragment_end > length)
return;
if (fragment_length == 0)
{
// NOTE: Empty messages still require an empty fragment to complete it
if (fragment_offset == 0 && m_missing.Count > 0)
{
Range firstRange = (Range)m_missing[0];
if (firstRange.End == 0)
{
m_missing.RemoveAt(0);
}
}
return;
}
for (int i = 0; i < m_missing.Count; ++i)
{
Range range = (Range)m_missing[i];
if (range.Start >= fragment_end)
break;
if (range.End > fragment_offset)
{
int copyStart = System.Math.Max(range.Start, fragment_offset);
int copyEnd = System.Math.Min(range.End, fragment_end);
int copyLength = copyEnd - copyStart;
Array.Copy(buf, off + copyStart - fragment_offset, m_body, copyStart, copyLength);
if (copyStart == range.Start)
{
if (copyEnd == range.End)
{
m_missing.RemoveAt(i--);
}
else
{
range.Start = copyEnd;
}
}
else
{
if (copyEnd != range.End)
{
m_missing.Insert(++i, new Range(copyEnd, range.End));
}
range.End = copyStart;
}
}
}
}
internal void Reset()
{
m_missing.Clear();
m_missing.Add(new Range(0, m_body.Length));
}
private sealed class Range
{
private int m_start, m_end;
internal Range(int start, int end)
{
this.m_start = start;
this.m_end = end;
}
public int Start
{
get { return m_start; }
set { this.m_start = value; }
}
public int End
{
get { return m_end; }
set { this.m_end = value; }
}
}
}
}
|