-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshared.py
148 lines (131 loc) · 5.43 KB
/
shared.py
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
138
139
140
141
142
143
144
145
146
147
148
"""
This module contains classes shared by boiler, gateway and telnetproxy
"""
from queue import Queue, Empty
import socket
import platform
import logging
from typing import Annotated
import annotated_types
import hargconfig
#----------------------------------------------------------#
SOCKET_TIMEOUT= 0.2
BUFF_SIZE= 1024
#----------------------------------------------------------#
class HargInfo():
""" a data class to store the HargInfo"""
gw_webapp: str = None # HargaWebApp version eg 6.4.1
gw_sn: str = None # IGW serial number
class SharedData():
"""
This class is used to share data between the gateway and the boiler.
"""
gw_port: Annotated[int, annotated_types.Gt(0)]
bl_port: Annotated[int, annotated_types.Gt(0)]
gw_addr: Annotated[bytes, annotated_types.MaxLen(15)]
bl_addr: Annotated[bytes, annotated_types.MaxLen(15)]
gwt_port: Annotated[int, annotated_types.Gt(0)]
def __init__(self):
self.gw_port = 0 # source port from which gateway is sending
self.gw_addr= b'' # to save the gateway ip adress when discovered
self.bl_addr= b'' # to save the boiler ip address when discovered
self.bl_port= 0 # destination port to which boiler is listening
self.gwt_port = 0 # source telnet port from which gateway is sending
class SharedDataReceiver(SharedData):
"""
This class extends SharedData class with a queue to receive data from
and a handler to process the received data.
"""
rq: Queue
config: hargconfig.HargConfig = None
def __init__(self):
super().__init__()
self.config= hargconfig.HargConfig()
self.rq = Queue()
def handle(self):
"""
This method handles received messages from the queue.
"""
try:
msg = self.rq.get(block=True, timeout=10)
logging.debug('handleReceiveQueue: received %s', msg)
if msg.startswith('GW_ADDR:'):
self.gw_addr = bytes(msg.split(':')[1],'ascii')
logging.debug('handleReceiveQueue: gw_addr=%s', self.gw_addr)
elif msg.startswith('GW_PORT:'):
self.gw_port = int(msg.split(':')[1])
logging.debug('handleReceiveQueue: gw_port=%d', self.gw_port)
elif msg.startswith('BL_ADDR:'):
self.bl_addr = bytes(msg.split(':')[1],'ascii')
logging.debug('handleReceiveQueue: bl_addr=%s', self.bl_addr)
elif msg.startswith('BL_PORT:'):
self.bl_port = int(msg.split(':')[1])
logging.debug('handleReceiveQueue: bl_port=%d', self.bl_port)
else:
logging.debug('handleReceiveQueue: unknown message %s', msg)
except Empty:
logging.debug('handleReceiveQueue: no message received')
def queue(self) -> Queue:
"""
This method returns the queue to receive data from.
"""
return self.rq
class ListenerSender(SharedDataReceiver):
"""
This class extends SharedDataReceiver class with a socket to listen
and a socket to resend data.
"""
listen: socket.socket
resend: socket.socket
src_iface: bytes
dst_iface: bytes
sq: Queue
bound: bool = False
def __init__(self, sq: Queue, src_iface: bytes,dst_iface: bytes):
super().__init__()
self.sq = sq # the queue to send what i discover about the network
self.src_iface = src_iface # network interface where to listen
self.dst_iface = dst_iface # network interface where to resend
self.bound= False
self.listen= socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
self.listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
self.listen.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
if platform.system() == 'Linux':
# pylint: disable=no-member
self.listen.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, src_iface)
self.resend= socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
self.resend.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
self.resend.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
if platform.system() == 'Linux':
# pylint: disable=no-member
self.resend.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, dst_iface)
self.resend.settimeout(SOCKET_TIMEOUT)
def handle_first(self, data, addr):
"""
This method handles the discovery of caller's ip address and port.
This method must be implemented in the child class.
"""
def send(self, data):
"""
This method resends received data to the destination.
This method must be implemented in the child class.
"""
def handle_data(self, data: bytes, addr: tuple):
"""
This method handles received data.
This method must be implemented in the child class.
"""
def loop(self):
"""
This method is the main loop of the class.
"""
data: bytes
addr: tuple
while True:
logging.debug('waiting data')
data, addr = self.listen.recvfrom(BUFF_SIZE)
logging.debug('received buffer of %d bytes from %s : %d', len(data), addr[0], addr[1])
logging.debug('%s', data)
self.handle_first(data, addr)
self.handle_data(data, addr)
self.send(data)