-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathip_frag.cpp
More file actions
90 lines (80 loc) · 2.09 KB
/
Copy pathip_frag.cpp
File metadata and controls
90 lines (80 loc) · 2.09 KB
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
#include "ip_frag.h"
ip_frag::ip_frag()
{
}
ip_frag::~ip_frag()
{
}
//!
//! \brief unpack 解封
//! \param bin
//! \return
//!
IP::DataPackList ip_frag::unpack(const QByteArray &in)
{
IP::DataPackList out;
const char *ptr = in.data();
const int len = in.size();
for (int offset = 0; offset < len; )
{
IP::Header *hdr = (IP::Header *)(ptr + offset);
offset += hdr->length;
out.append(IP::DataPack(hdr));
}
return out;
}
bool ip_frag::check(IP::Header *rhs)const
{
IP::Header tmhdr = *rhs;
tmhdr.checksum = 0;
const quint16 csum = IP::CheckSum((quint16*)&tmhdr, sizeof(IP::Header));
return csum == rhs->checksum;
}
//!
//! \brief ip_frag::is_match 匹配id,源地址,目的地址,和协议。是否相同
//! \param first
//! \param rhs
//! \return
//!
bool ip_frag::is_match(IP::Header *first, IP::Header *rhs)const
{
return (first->id == rhs->id) &&
(first->addrs == rhs->addrs) &&
(first->addrd == rhs->addrd) &&
(first->protocol == rhs->protocol);
}
QByteArray ip_frag::reassemble(const IP::DataPackList &dpl)
{
QByteArray out;
IP::Header *first_hdr = 0;
foreach (const IP::DataPack &var, dpl)
{
// 校验和是否合法
if (check(var.head()))
continue;
// 匹配多个分片
if (!first_hdr)
first_hdr = var.head();
else if (!is_match(first_hdr, var.head()))
continue;
const quint16 length = var.head()->length - (var.head()->headlen <<2);
// 有多个分片,取出分片内的数据
if (var.head()->flag & IP::IP_MoreFragment)
{
const quint16 offset = var.head()->offset <<3;
out.insert(offset, var.data(), length);
}
// 非分片,则不考虑数据的偏移
else if (var.head()->flag & IP::IP_DontFragment)
{
out.append(var.data(), length);
}
// 单帧数据取出后返回
else
{
out = QByteArray(var.data(), length);
break;
}
}
return out;
}