Composer.py
2.82 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
91
92
93
94
95
96
97
98
99
100
101
102
103
"""
@author Georg Hopp
"""
import struct
class Composer(object):
def __init__(self):
self._name_ofs = {}
def compose(self, message):
self._name_ofs = {}
header = struct.pack(
'!HHHHHH',
message._msg_id,
message._flags,
len(message._queries),
len(message._answers),
len(message._authoritys),
len(message._additionals)
)
queries = answers = authoritys = additionals = ''
ofs = len(header)
if message._queries:
queries = self._composeQueries(message, ofs)
ofs += len(queries)
if message._answers:
answers = self._composeAnswers(message, ofs)
ofs += len(answers)
if message._authoritys:
authoritys = self._composeAuthoritys(message, ofs)
ofs += len(authoritys)
if message._additionals:
additionals = self._composeAdditionals(message, ofs)
return header + queries + answers + authoritys + additionals
def _composeQueries(self, message, ofs):
encoded = ''
for query in message._queries:
name, typ, cls = query
ename = self._encodeName(name, ofs)
query = struct.pack('!%dsHH'%len(ename), ename, typ, cls)
ofs += len(query)
encoded += query
return encoded
def _composeAnswers(self, message, ofs):
encoded = ''
for answer in message._answers:
record = self._composeResourceRecord(answer, ofs)
ofs += len(record)
encoded += record
return encoded
def _composeAuthoritys(self, message, ofs):
encoded = ''
for authority in message._authoritys:
record = self._composeResourceRecord(authority, ofs)
ofs += len(record)
encoded += record
return encoded
def _composeAdditionals(self, message, ofs):
encoded = ''
for additional in message._additionals:
record = self._composeResourceRecord(additional, ofs)
ofs += len(record)
encoded += record
return encoded
def _composeResourceRecord(self, record, ofs):
name, typ, cls, ttl, data = record
ename = self._encodeName(name, ofs)
return struct.pack('!%dsHHLH%ds'%(len(ename), len(data)),
ename, typ, cls, ttl, len(data), data)
def _encodeName(self, name, ofs):
if name in self._name_ofs:
name = struct.pack('!H',
int('1100000000000000', 2) | self._name_ofs[name])
else:
self._name_ofs[name] = ofs
name = ''.join([struct.pack('B%ds'%len(p), len(p), p)
for p in name.split('.')]) + '\x00'
return name
# vim: set ft=python et ts=4 sw=4 sts=4: