Skip to content

Commit ec4fefd

Browse files
author
Ivan Bannikov
committed
moved all Response and Request classes into modules. Added new port_no param for EPMDProtocol constructor.
1 parent 60660c4 commit ec4fefd

File tree

4 files changed

+171
-152
lines changed

4 files changed

+171
-152
lines changed

epmd.py

Lines changed: 2 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,11 @@
11
# coding: utf-8
22

33
import asyncio
4-
import functools
5-
6-
from bitstring import Bits, BitArray, ConstBitStream
7-
8-
9-
TCP_PROTOCOL = 0
10-
IP_V4 = 1
11-
12-
NORMAL_ERL_NODE = 77
13-
HIDDEN_NODE = 72
14-
15-
16-
HIGHEST_VERSION = 5
17-
LOWEST_VERSION = 5
18-
19-
20-
class EPMDRequest:
21-
22-
def encode(self):
23-
raw_packet = self._get_raw_data()
24-
packet_len = len(raw_packet) // 8
25-
fullbuf = BitArray()
26-
fullbuf.append(Bits(uint=packet_len, length=16))
27-
fullbuf.append(raw_packet)
28-
return fullbuf.bytes
29-
30-
31-
class Alive2Request(EPMDRequest):
32-
33-
def __init__(self, port_no,
34-
node_type=NORMAL_ERL_NODE,
35-
protocol=TCP_PROTOCOL,
36-
high_ver=HIGHEST_VERSION,
37-
low_ver=LOWEST_VERSION,
38-
node_name='pynode@localhost',
39-
extra=None):
40-
self.port_no = port_no
41-
self.node_type = node_type
42-
self.protocol = protocol
43-
self.high_ver = high_ver
44-
self.low_ver = low_ver
45-
self.node_name = node_name
46-
self.extra = extra
47-
48-
def _get_raw_data(self):
49-
buf = BitArray()
50-
51-
# ALIVE2_REQ
52-
buf.append(Bits(uint=120, length=8))
53-
54-
# PORT_NO
55-
buf.append(Bits(uint=self.port_no, length=16))
56-
57-
# NODE_TYPE
58-
buf.append(Bits(uint=self.node_type, length=8))
59-
60-
# PROTOCOL
61-
buf.append(Bits(uint=self.protocol, length=8))
62-
63-
# HGHEST VERSION
64-
buf.append(Bits(uint=self.high_ver, length=16))
65-
66-
# LOWEST VERSION
67-
buf.append(Bits(uint=self.low_ver, length=16))
68-
69-
node_name_encoded = self.node_name.encode()
70-
nlen = len(node_name_encoded)
71-
72-
# NLEN
73-
buf.append(Bits(uint=nlen, length=16))
74-
75-
# NODENAME
76-
buf.append(Bits(bytes=node_name_encoded, length=nlen * 8))
77-
78-
# EXTRA
79-
if self.extra is not None:
80-
extra_encoded = self.extra.encode()
81-
elen = len(extra_encoded)
82-
buf.append(Bits(uint=elen, length=16))
83-
buf.append(Bits(bytes=extra_encoded, length=elen * 8))
84-
else:
85-
buf.append(Bits(uint=0, length=16))
86-
return buf
87-
88-
89-
class NamesRequest(EPMDRequest):
90-
91-
def _get_raw_data(self):
92-
return BitArray(Bits(uint=110, length=8))
93-
94-
95-
class EPMDresponse:
96-
97-
def __init__(self, data):
98-
self._raw_data = data
99-
100-
101-
class Alive2Response(EPMDresponse):
102-
103-
def __init__(self, data, success, creation):
104-
super(Alive2Response, self).__init__(data)
105-
self.success = success
106-
self.creation = creation
107-
108-
109-
class UnknownEPMDResponse(EPMDresponse):
110-
pass
111-
112-
113-
class EPMDProtocol(asyncio.Protocol):
114-
115-
ERROR = -1
116-
INIT = 1
117-
SENT_REG = 2
118-
WAIT_FOR_NAMES = 3
119-
120-
def __init__(self, loop):
121-
self.loop = loop
122-
self.state = self.INIT
123-
124-
def connection_made(self, transport):
125-
self._transport = transport
126-
self.send_epmd_request(Alive2Request(port_no=7170))
127-
128-
def data_received(self, data):
129-
if self.state == self.INIT:
130-
response = self._unpack_epmd_resp(data)
131-
if response.success:
132-
print('Registering in EPMD success!')
133-
#self.send_epmd_request(NamesRequest())
134-
#self.state = self.WAIT_FOR_NAMES
135-
elif self.state == self.WAIT_FOR_NAMES:
136-
print(data)
137-
138-
def connection_lost(self, exc):
139-
print('Connection to EPMD closed')
140-
self.loop.stop()
141-
142-
def _unpack_epmd_resp(self, data):
143-
buf = ConstBitStream(data)
144-
ptype = buf.read('uint:8')
145-
if ptype == 121:
146-
success = buf.read('uint:8')
147-
creation = buf.read('bytes:2')
148-
return Alive2Response(data, success == 0, creation)
149-
else:
150-
return UnknownEPMDResponse(data)
151-
152-
def send_epmd_request(self, request):
153-
self._transport.write(request.encode())
154-
4+
from protocol import EPMDProtocol
1555

1566
loop = asyncio.get_event_loop()
1577

158-
epmd = EPMDProtocol(loop)
8+
epmd = EPMDProtocol(7170, loop)
1599
coro = loop.create_connection(lambda : epmd, '127.0.0.1', 4369)
16010

16111
loop.run_until_complete(coro)

protocol.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# coding: utf-8
2+
3+
import asyncio
4+
5+
from bitstring import ConstBitStream
6+
7+
from request import Alive2Request, NamesRequest
8+
from response import UnknownEPMDResponse, Alive2Response
9+
10+
11+
class EPMDProtocol(asyncio.Protocol):
12+
13+
ERROR = -1
14+
INIT = 1
15+
SENT_REG = 2
16+
WAIT_FOR_NAMES = 3
17+
18+
def __init__(self, node_port, loop):
19+
self.loop = loop
20+
self.state = self.INIT
21+
self.node_port = node_port
22+
23+
def connection_made(self, transport):
24+
self._transport = transport
25+
self.send_epmd_request(Alive2Request(port_no=self.node_port))
26+
27+
def data_received(self, data):
28+
if self.state == self.INIT:
29+
response = self._unpack_epmd_resp(data)
30+
if response.success:
31+
print('Registering in EPMD success!')
32+
#self.send_epmd_request(NamesRequest())
33+
#self.state = self.WAIT_FOR_NAMES
34+
elif self.state == self.WAIT_FOR_NAMES:
35+
print(data)
36+
37+
def connection_lost(self, exc):
38+
print('Connection to EPMD closed')
39+
self.loop.stop()
40+
41+
def _unpack_epmd_resp(self, data):
42+
buf = ConstBitStream(data)
43+
ptype = buf.read('uint:8')
44+
if ptype == 121:
45+
success = buf.read('uint:8')
46+
creation = buf.read('bytes:2')
47+
return Alive2Response(data, success == 0, creation)
48+
else:
49+
return UnknownEPMDResponse(data)
50+
51+
def send_epmd_request(self, request):
52+
print('sending request...')
53+
self._transport.write(request.encode())

request.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# coding: utf-8
2+
3+
4+
from bitstring import Bits, BitArray, ConstBitStream
5+
6+
7+
TCP_PROTOCOL = 0
8+
IP_V4 = 1
9+
10+
NORMAL_ERL_NODE = 77
11+
HIDDEN_NODE = 72
12+
13+
14+
HIGHEST_VERSION = 5
15+
LOWEST_VERSION = 5
16+
17+
18+
class EPMDRequest:
19+
20+
def encode(self):
21+
raw_packet = self._get_raw_data()
22+
packet_len = len(raw_packet) // 8
23+
fullbuf = BitArray()
24+
fullbuf.append(Bits(uint=packet_len, length=16))
25+
fullbuf.append(raw_packet)
26+
return fullbuf.bytes
27+
28+
def _get_raw_data(self):
29+
raise NotImplementedError("protected method _get_raw_data should be "
30+
"implemented!")
31+
32+
33+
class Alive2Request(EPMDRequest):
34+
35+
def __init__(self, port_no,
36+
node_type=NORMAL_ERL_NODE,
37+
protocol=TCP_PROTOCOL,
38+
high_ver=HIGHEST_VERSION,
39+
low_ver=LOWEST_VERSION,
40+
node_name='pynode',
41+
extra=None):
42+
self.port_no = port_no
43+
self.node_type = node_type
44+
self.protocol = protocol
45+
self.high_ver = high_ver
46+
self.low_ver = low_ver
47+
self.node_name = node_name
48+
self.extra = extra
49+
50+
def _get_raw_data(self):
51+
buf = BitArray()
52+
53+
# ALIVE2_REQ
54+
buf.append(Bits(uint=120, length=8))
55+
56+
# PORT_NO
57+
buf.append(Bits(uint=self.port_no, length=16))
58+
59+
# NODE_TYPE
60+
buf.append(Bits(uint=self.node_type, length=8))
61+
62+
# PROTOCOL
63+
buf.append(Bits(uint=self.protocol, length=8))
64+
65+
# HGHEST VERSION
66+
buf.append(Bits(uint=self.high_ver, length=16))
67+
68+
# LOWEST VERSION
69+
buf.append(Bits(uint=self.low_ver, length=16))
70+
71+
node_name_encoded = self.node_name.encode()
72+
nlen = len(node_name_encoded)
73+
74+
# NLEN
75+
buf.append(Bits(uint=nlen, length=16))
76+
77+
# NODENAME
78+
buf.append(Bits(bytes=node_name_encoded, length=nlen * 8))
79+
80+
# EXTRA
81+
if self.extra is not None:
82+
extra_encoded = self.extra.encode()
83+
elen = len(extra_encoded)
84+
buf.append(Bits(uint=elen, length=16))
85+
buf.append(Bits(bytes=extra_encoded, length=elen * 8))
86+
else:
87+
buf.append(Bits(uint=0, length=16))
88+
return buf
89+
90+
91+
class NamesRequest(EPMDRequest):
92+
93+
def _get_raw_data(self):
94+
return BitArray(Bits(uint=110, length=8))

response.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# coding: utf-8
2+
3+
4+
from bitstring import Bits, BitArray, ConstBitStream
5+
6+
7+
class EPMDresponse:
8+
9+
def __init__(self, data):
10+
self._raw_data = data
11+
12+
13+
class Alive2Response(EPMDresponse):
14+
15+
def __init__(self, data, success, creation):
16+
super(Alive2Response, self).__init__(data)
17+
self.success = success
18+
self.creation = creation
19+
20+
21+
class UnknownEPMDResponse(EPMDresponse):
22+
pass

0 commit comments

Comments
 (0)