-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathresponse.py
More file actions
137 lines (99 loc) · 3.19 KB
/
response.py
File metadata and controls
137 lines (99 loc) · 3.19 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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# coding: utf-8
import re
from collections import namedtuple
from struct import pack, unpack, unpack_from, calcsize
ALIVE2_RESP = 121
PORT2_RESP = 119
match_node_info = re.compile('^name (\w+) at port (\d+)$')
NodeInfo = namedtuple('NodeInfo', ['name', 'port'])
def parse_node_info(info):
name, port = match_node_info.match(info.decode('utf-8')).groups()
return NodeInfo(name, int(port))
class EPMDresponse:
def __init__(self, data):
self._raw_data = data
class Alive2Response(EPMDresponse):
def __init__(self, data, success, creation):
super(Alive2Response, self).__init__(data)
self.success = success
self.creation = creation
@classmethod
def decode(cls, data):
RES_TYPE, = unpack('>B', data[:1])
if RES_TYPE != ALIVE2_RESP:
return
success, creation = unpack('>B2s', data[1:])
return Alive2Response(data, success == 0, creation)
class PortResponse(EPMDresponse):
def __init__(self, port_no,
node_type,
protocol,
high_ver,
low_ver,
node_name,
extra):
self.port_no = port_no
self.node_type = node_type
self.high_ver = high_ver
self.low_ver = low_ver
self.node_name = node_name
self.extra = extra
self.protocol = protocol
@classmethod
def decode(cls, data):
RES_TYPE, status = unpack('>BB', data[:2])
if RES_TYPE != PORT2_RESP or status > 0:
return
pack_fmt = '>HBBHHH'
port_no, node_type, protocol, high_ver, low_ver, nlen = unpack_from(
pack_fmt,
data,
2
)
node_name, elen = unpack_from(
'>{nlen}sH'.format(nlen=nlen),
data,
calcsize(pack_fmt) + 2
)
node_name = node_name.decode('utf-8')
if elen:
extra = unpack_from(
'>{elen}s'.format(elen=elen),
data,
calcsize(pack_fmt) + 2 + nlen
)
else:
extra = None
return cls(port_no=port_no,
node_type=node_type,
protocol=protocol,
high_ver=high_ver,
low_ver=low_ver,
node_name=node_name,
extra=extra)
def __repr__(self):
return '{node} on {port}'.format(
node=self.node_name,
port=self.port_no
)
class NamesResponse(EPMDresponse):
def __init__(self, nodes):
self.nodes = nodes
@classmethod
def decode(cls, data):
port_non = unpack_from('>H', data, 0)
nodes = []
for nodeinfo in data[4:].split(b'\n'):
if nodeinfo:
nodes.append(parse_node_info(nodeinfo))
return cls(nodes)
class UnknownEPMDResponse(EPMDresponse):
pass
class DistributionRequest:
def __init__(self, version, flags, node_name):
self.version = version
self.flags = flags
self.node_name = node_name
@classmethod
def decode(cls, packet):
return cls(version, flags, node_name)