-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathIpReassemblyBufferHoleList.cpp
117 lines (99 loc) · 2.91 KB
/
IpReassemblyBufferHoleList.cpp
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
#include "IpReassemblyBufferHoleList.h"
#include <limits.h>
#include <assert.h>
namespace FeatureExtractor {
IpReassemblyBufferHoleList::Hole::Hole()
: start(0), end(SIZE_MAX), next(nullptr)
{}
IpReassemblyBufferHoleList::Hole::Hole(size_t start, size_t end, Hole *next)
{
this->start = start;
this->end = end;
this->next = next;
}
IpReassemblyBufferHoleList::IpReassemblyBufferHoleList()
: first_hole(new Hole())
{}
IpReassemblyBufferHoleList::~IpReassemblyBufferHoleList()
{
// Deallocate linked list of holes
Hole *next;
while (first_hole) {
next = first_hole->next;
delete first_hole;
first_hole = next;
}
}
bool IpReassemblyBufferHoleList::is_empty() const
{
return (first_hole == nullptr);
}
/*
* RFC 815 - section 3: Fragment Processing Algorithm
* Terms start (end) in code bellow corresponds to first (last) in RFC.
*/
void IpReassemblyBufferHoleList::add_fragment(size_t frag_start, size_t frag_end, bool is_last_frag) {
// Should not insert to completed datagram
assert(!this->is_empty() && "Attempt to insert fragment to reassembled datagram");
Hole *prev = nullptr;
Hole *hole = this->first_hole;
while (hole) { // 7. + 1. Loop finished when no next hole descriptor
// 1.-3. Find hole that fragment fits
while (hole && (frag_start > hole->end || frag_end < hole->start)) {
// Part of 6. If last fragment change update last hole end (initiated to infinity)
if (is_last_frag && !hole->next) {
hole->end = frag_end;
// If hole makes no sense, destroy it
if (hole->start > hole->end) {
if (prev)
prev->next = hole->next;
else
first_hole = hole->next;
delete hole;
hole = nullptr;
break;
}
}
// 1. Select the next hole descriptor from the hole descriptor list.
prev = hole;
hole = hole->next;
} // End of 1.-3. Find hole...
if (hole) {
Hole *next = hole->next;
// 5. New hole before fragment
if (frag_start > hole->start) {
Hole *new_hole = new Hole(hole->start, frag_end - 1, next);
if (prev)
prev->next = new_hole;
else
first_hole = new_hole;
prev = new_hole;
}
// 6. New hole after fragment
// If last fragment change update last hole end (initiated to infinity)
if (is_last_frag && !next) {
hole->end = frag_end;
}
if (frag_end < hole->end) {
Hole *new_hole = new Hole(frag_end + 1, hole->end, next);
if (prev)
prev->next = new_hole;
else
first_hole = new_hole;
prev = new_hole;
}
// 4. Delete hole descriptor
delete hole;
// 1. Select the next hole descriptor
hole = next;
// If no hole except the one to be deleted, the list is empty now
if (!prev && !next)
first_hole = nullptr;
}
}
// 8: If the hole descriptor list is now empty, the datagram is now complete
if (this->is_empty()) {
//TODO: got the datagram bitch!
}
}
}