You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.8 KiB
103 lines
2.8 KiB
"""
|
|
@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:
|