Updated filtering and API

This commit is contained in:
Antonio Matraia 2021-03-29 21:06:18 +02:00
parent 65dba6b290
commit 7c7c9955cf
2 changed files with 179 additions and 63 deletions

View File

@ -27,7 +27,6 @@ import os
import time import time
import re import re
import configparser import configparser
import datetime
import signal import signal
from datetime import datetime from datetime import datetime
import bisect import bisect
@ -46,7 +45,7 @@ def long2ip(lng):
return ip return ip
## gestione liste LH ecc ## ## LH list management ##
def inserisci_lista(lista, elemento, n_max): def inserisci_lista(lista, elemento, n_max):
if (len(lista) < n_max): if (len(lista) < n_max):
lista.append(elemento) lista.append(elemento)
@ -55,6 +54,21 @@ def inserisci_lista(lista, elemento, n_max):
lista[i] = lista[i+1] lista[i] = lista[i+1]
lista[n_max-1] = elemento lista[n_max-1] = elemento
def inserisci_listaD(lista, elemento, n_max):
for i in lista:
if (i[1] == elemento[1]):
lista.remove(i)
break
if (len(lista) < n_max):
lista.append(elemento)
else:
for i in range(n_max - 1):
lista[i] = lista[i+1]
lista[n_max-1] = elemento
def stampa_lista(lista): def stampa_lista(lista):
for i in range(len(lista)): for i in range(len(lista)):
print(lista[len(lista)-i-1]) print(lista[len(lista)-i-1])
@ -80,7 +94,7 @@ def check_string(l):
def RecvData(sock,recvPackets): def RecvData(sock,recvPackets):
while True: while True:
data,addr = sock.recvfrom(1024) # bloccante se non ricevo niente data,addr = sock.recvfrom(1024) # block if I don't receive anything
recvPackets.put((data,addr)) recvPackets.put((data,addr))
@ -140,7 +154,7 @@ def TimeoutNodi(cl):
cl.remove(c) cl.remove(c)
def TimeoutTX(t, t_lock, r_lock, lista_lh): def TimeoutTX(t, t_lock, r_lock, lista_lh, lista_lhd):
while True: while True:
if (t[1] < 5): if (t[1] < 5):
t[1] += 0.1 t[1] += 0.1
@ -148,7 +162,8 @@ def TimeoutTX(t, t_lock, r_lock, lista_lh):
t[0] = 0 t[0] = 0
printlog('Network watchdog has expired') printlog('Network watchdog has expired')
inserisci_lista(lista_lh, [check_string(t[2]), check_string(t[3]), check_string(t[4]), t[5], datetime.fromtimestamp(t[6]).strftime("%d-%m-%Y %H-%M-%S"), round(time.time() - t[6]) ], 20) inserisci_lista(lista_lh, [check_string(t[2]), check_string(t[3]), check_string(t[4]), t[5], datetime.fromtimestamp(t[6]).strftime("%d-%m-%Y %H-%M-%S"), round(time.time() - t[6]) ], 20)
t[0] = 0 inserisci_listaD(lista_lhd, [check_string(t[2]), check_string(t[3]), check_string(t[4]), t[5], datetime.fromtimestamp(t[6]).strftime("%d-%m-%Y %H-%M-%S"), round(time.time() - t[6]) ], 20)
t[1] = 0
t[2] = '' t[2] = ''
t[3] = '' t[3] = ''
t[4] = '' t[4] = ''
@ -173,21 +188,39 @@ def canTrasmit(cs, re_en):
global WHITE_LIST global WHITE_LIST
call_sp = re.split(r'[-/]', cs) call_sp = re.split(r'[-/]', cs)
call = call_sp[0] call = call_sp[0]
if inlist(WHITE_LIST, call):
return True ## always block a stream from repeater ###
if inlist(BLACK_LIST, call):
return False
if (len(call_sp) > 1): if (len(call_sp) > 1):
if (call_sp[1] == 'RPT'): if (call_sp[1] == 'RPT'):
return False return False
if re_en:
## case CheckRE == 1 ###
if (re_en == 1):
if inlist(WHITE_LIST, call):
return True
if inlist(BLACK_LIST, call):
return False
if (re.match(r'^\d?[A-Z]{1,2}\d{1,4}[A-Z]{1,3}$',call,re.IGNORECASE) and (len(call) <= 8)): if (re.match(r'^\d?[A-Z]{1,2}\d{1,4}[A-Z]{1,3}$',call,re.IGNORECASE) and (len(call) <= 8)):
return True return True
else: else:
return False return False
else:
## case CheckRE == 0 ###
if (re_en == 0):
if inlist(WHITE_LIST, call):
return True
if inlist(BLACK_LIST, call):
return False
return True return True
## case CheckRE == -1 ###
if (re_en == -1):
if inlist(BLACK_LIST, call):
return False
if inlist(WHITE_LIST, call):
return True
return False
def lista_gw(cl): def lista_gw(cl):
info = '' info = ''
@ -236,9 +269,12 @@ def blacklist(f_bl, t_reload, cli):
printlog('Reload the Blacklist from File') printlog('Reload the Blacklist from File')
for row in file: for row in file:
content = row.strip() content = row.strip()
# riga valida
# valid line (not a comment)
if ((len(content) > 3) and (content[0] != '#')): if ((len(content) > 3) and (content[0] != '#')):
c_split = content.split(':') c_split = content.split(':')
for i in range(len(c_split)):
c_split[i] = c_split[i].strip()
# CALL # CALL
if (len(c_split) == 1 or c_split[0] == 'CS'): if (len(c_split) == 1 or c_split[0] == 'CS'):
@ -274,11 +310,12 @@ def blacklist(f_bl, t_reload, cli):
file.close() file.close()
except Exception as ex: except Exception as ex:
printlog('Failed to load Blacklist from File ') printlog('Failed to load Blacklist from File ' + str(ex) )
BLACK_LIST = BL_TMP.copy() BLACK_LIST = BL_TMP.copy()
WHITE_LIST = WL_TMP.copy() WHITE_LIST = WL_TMP.copy()
GW_BL = GW_TMP.copy() GW_BL = GW_TMP.copy()
IP_BL = IP_TMP.copy() IP_BL = IP_TMP.copy()
printlog('Loaded ' + str(len(BLACK_LIST)) + '/CS ' + str(len(WHITE_LIST)) + '/AL ' + str(len(GW_BL)) + '/GW ' + str(len(IP_BL)) + '/IP')
f_time_old = f_time f_time_old = f_time
update_clients(cli) update_clients(cli)
else: else:
@ -286,7 +323,7 @@ def blacklist(f_bl, t_reload, cli):
time.sleep(t_reload) time.sleep(t_reload)
## lettura file configurazione ## ## reading configuration file ##
def ReadConfig(f,p): def ReadConfig(f,p):
config = configparser.ConfigParser() config = configparser.ConfigParser()
@ -305,6 +342,13 @@ def ReadConfig(f,p):
except: except:
file_rotate = "1" # to keep file-rotation by default with timestamp file_rotate = "1" # to keep file-rotation by default with timestamp
try:
en_ext_cmd = int(config['Log']['EnableExtendedCommands'])
except:
en_ext_cmd = 0 # extended commands disabled by default
try: try:
port = int(config['Network']['Port']) port = int(config['Network']['Port'])
except: except:
@ -316,6 +360,10 @@ def ReadConfig(f,p):
try: try:
CheckRE = int(config['Block List']['CheckRE']) CheckRE = int(config['Block List']['CheckRE'])
if (CheckRE > 1):
CheckRE = 1
if (CheckRE < -1):
CheckRE = -1
except: except:
CheckRE = 1 CheckRE = 1
@ -336,6 +384,8 @@ def ReadConfig(f,p):
p.append(t_reload_blacklist) # 7 p.append(t_reload_blacklist) # 7
p.append(file_rotate) # 8 p.append(file_rotate) # 8
p.append(CheckRE) # 9 p.append(CheckRE) # 9
p.append(en_ext_cmd) #10
def sanitize_msg(data): def sanitize_msg(data):
@ -370,14 +420,17 @@ def RunServer(config):
rx_lock = [] rx_lock = []
rx_lock_tout = {} rx_lock_tout = {}
# lista LH # LH list
LH = [] LH = []
# lista bloccati LHD = []
BL = []
id = 1 # id nodo # muted list
BL = []
BLD = []
id = 1 # id gw
id_str = 1 # id stream id_str = 1 # id stream
tx = [0, 0, '', '', '', 0, 0] # id_nodo, tout, gateway, src, dest, id_stream, start_time tx = [0, 0, '', '', '', 0, 0] # id_gw, tout, gateway, src, dest, id_stream, start_time
refl_name = config[1] refl_name = config[1]
refl_desc = config[2] refl_desc = config[2]
@ -392,14 +445,20 @@ def RunServer(config):
CheckRE = config[9] CheckRE = config[9]
en_ext_cmd = config[10]
recvPackets = queue.Queue() recvPackets = queue.Queue()
print('Starting YSFReflector-' + version) print('Starting YSFReflector-' + version)
printlog('Starting YSFReflector-' + version) printlog('Starting YSFReflector-' + version)
if (en_ext_cmd == 1):
printlog('Extended Commands Enabled')
else:
printlog('Extended Commands Disabled')
threading.Thread(target=RecvData,args=(s,recvPackets)).start() threading.Thread(target=RecvData,args=(s,recvPackets)).start()
threading.Thread(target=ElencoNodi,args=(clients,)).start() threading.Thread(target=ElencoNodi,args=(clients,)).start()
threading.Thread(target=TimeoutNodi,args=(clients,)).start() threading.Thread(target=TimeoutNodi,args=(clients,)).start()
threading.Thread(target=TimeoutTX,args=(tx,rx_lock_tout,rx_lock,LH)).start() threading.Thread(target=TimeoutTX,args=(tx,rx_lock_tout,rx_lock,LH,LHD)).start()
if (len(f_blacklist) > 0): if (len(f_blacklist) > 0):
threading.Thread(target=blacklist,args=(f_blacklist,tr_blacklist,clients)).start() threading.Thread(target=blacklist,args=(f_blacklist,tr_blacklist,clients)).start()
@ -407,7 +466,7 @@ def RunServer(config):
while True: while True:
data_ns, addr = recvPackets.get() # bloccante se coda vuota data_ns, addr = recvPackets.get() # blocked if queue is empty
data = sanitize_msg(data_ns) data = sanitize_msg(data_ns)
cmd = data[0:4] cmd = data[0:4]
if (cmd == b'YSFP'): if (cmd == b'YSFP'):
@ -468,9 +527,9 @@ def RunServer(config):
else: else:
if (id_corr not in rx_lock): if (id_corr not in rx_lock):
rx_lock.append(id_corr) rx_lock.append(id_corr)
inserisci_lista(BL, [check_string(data[4:14].decode().strip()), check_string(data[14:24].decode().strip()), check_string(data[24:34].decode().strip()), -1, datetime.fromtimestamp(time.time()).strftime("%d-%m-%Y %H-%M-%S"), -1 ], 20) inserisci_lista(BL, [check_string(data[4:14].decode().strip()) + '/' + block_r, check_string(data[14:24].decode().strip()), check_string(data[24:34].decode().strip()), -1, datetime.fromtimestamp(time.time()).strftime("%d-%m-%Y %H-%M-%S"), -1 ], 20)
inserisci_listaD(BLD, [check_string(data[4:14].decode().strip()) + '/' + block_r, check_string(data[14:24].decode().strip()), check_string(data[24:34].decode().strip()), -1, datetime.fromtimestamp(time.time()).strftime("%d-%m-%Y %H-%M-%S"), -1 ], 20)
printlog('Data from ' + data[14:24].decode().strip().ljust(10) + ' at ' + data[4:14].decode().strip().ljust(10) + ' blocked/' + block_r) printlog('Data from ' + data[14:24].decode().strip().ljust(10) + ' at ' + data[4:14].decode().strip().ljust(10) + ' blocked/' + block_r)
# printlog('Bloccato: ' + data[14:24].decode().strip() + ' via ' + data[4:14].decode().strip())
rx_lock_tout[id_corr] = 0 rx_lock_tout[id_corr] = 0
if ((id_corr == tx[0]) and (id_corr != 0)): if ((id_corr == tx[0]) and (id_corr != 0)):
@ -484,6 +543,7 @@ def RunServer(config):
if (tx[0] != 0): if (tx[0] != 0):
printlog('Received end of transmission') printlog('Received end of transmission')
inserisci_lista(LH, [check_string(tx[2]), check_string(tx[3]), check_string(tx[4]), tx[5], datetime.fromtimestamp(tx[6]).strftime("%d-%m-%Y %H-%M-%S"), round(time.time() - tx[6]) ], 20) inserisci_lista(LH, [check_string(tx[2]), check_string(tx[3]), check_string(tx[4]), tx[5], datetime.fromtimestamp(tx[6]).strftime("%d-%m-%Y %H-%M-%S"), round(time.time() - tx[6]) ], 20)
inserisci_listaD(LHD, [check_string(tx[2]), check_string(tx[3]), check_string(tx[4]), tx[5], datetime.fromtimestamp(tx[6]).strftime("%d-%m-%Y %H-%M-%S"), round(time.time() - tx[6]) ], 20)
tx[0] = 0 tx[0] = 0
tx[2] = '' tx[2] = ''
tx[3] = '' tx[3] = ''
@ -492,7 +552,7 @@ def RunServer(config):
tx[6] = 0 tx[6] = 0
if (cmd == b'YSFS'): if (cmd == b'YSFS'):
# printlog('YSF server status enquiry from ' + addr[0] + ':' + str(addr[1])) printlog('YSF server status enquiry from ' + addr[0] + ':' + str(addr[1]))
if (len(clients) > 999): if (len(clients) > 999):
num_cli = 999 num_cli = 999
else: else:
@ -501,41 +561,95 @@ def RunServer(config):
s.sendto(str.encode(info),addr) s.sendto(str.encode(info),addr)
## messaggi per report attivo ## if (cmd == b'YSFV'):
if (cmd == b'QSRU'): printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1])) info = 'YSFV' + 'pYSFReflector' + ' ' + version
info = 'ASRU;' + str(round(time.time()-time_start)) + ';' s.sendto(str.encode(info),addr)
s.sendto(str.encode(info),addr)
if (cmd == b'YSFI'):
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
# info = 'YSFV' + 'pYSFReflector' + ' ' + version
# s.sendto(str.encode(info),addr)
if (cmd == b'QSRI'):
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
info = 'ASRI;' + str(refl_id) + ':' + refl_name + ':' + refl_desc + ';'
s.sendto(str.encode(info),addr)
## Extended Commands ##
if (en_ext_cmd == 1):
if (cmd == b'QSRU'):
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
info = 'ASRU;' + str(round(time.time()-time_start)) + ';'
s.sendto(str.encode(info),addr)
if (cmd == b'QGWL'): if (cmd == b'QSRI'):
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1])) printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
info = 'AGWL;' + lista_gw(clients) info = 'ASRI;' + str(refl_id) + ':' + refl_name + ':' + refl_desc + ':' + 'pYSFReflector' + ':' + version + ':' + str(CheckRE) + ';'
s.sendto(str.encode(info),addr) s.sendto(str.encode(info),addr)
if (cmd == b'QLHL'): if (cmd == b'QGWL'):
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1])) printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
info = 'ALHL;' + lista_invio(LH) info = 'AGWL;' + lista_gw(clients)
s.sendto(str.encode(info),addr) s.sendto(str.encode(info),addr)
if (cmd == b'QREJ'): if (cmd == b'QLHL'):
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1])) printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
info = 'AREJ;' + lista_invio(BL) info = 'ALHL;' + lista_invio(LH)
s.sendto(str.encode(info),addr) s.sendto(str.encode(info),addr)
if (cmd == b'QBLK'): if (cmd == b'QREJ'):
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1])) printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
s_info = '' info = 'AREJ;' + lista_invio(BL)
for c in BLACK_LIST: s.sendto(str.encode(info),addr)
s_info += c + ';'
info = 'ABLK;' + s_info if (cmd == b'QLHD'):
s.sendto(str.encode(info),addr) printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
info = 'ALHD;' + lista_invio(LHD)
s.sendto(str.encode(info),addr)
if (cmd == b'QRED'):
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
info = 'ARED;' + lista_invio(BLD)
s.sendto(str.encode(info),addr)
if (cmd == b'QACL'):
printlog('Received command ' + cmd.decode() + ' from: ' + addr[0] + ':' + str(addr[1]))
s_info = ''
info = 'AACL;CS/' + str(len(BLACK_LIST)) + '|' + 'AL/' + str(len(WHITE_LIST)) + '|' + 'GW/' + str(len(GW_BL)) + '|' + 'IP/' + str(len(IP_BL)) + ';'
i = 0
for c in BLACK_LIST:
s_info += 'CS:' + c + ';'
i += 1
if (i >= 20):
break
info += s_info
s_info = ''
i = 0
for c in WHITE_LIST:
s_info += 'AL:' + c + ';'
i += 1
if (i >= 20):
break
info += s_info
s_info = ''
i = 0
for c in GW_BL:
s_info += 'GW:' + c + ';'
i += 1
if (i >= 20):
break
info += s_info
s_info = ''
i = 0
for c in IP_BL:
s_info += 'IP:' + long2ip(c) + ';'
i += 1
if (i >= 20):
break
info += s_info
s.sendto(str.encode(info),addr)
s.close() s.close()
@ -566,7 +680,7 @@ def printlog(mess):
######## main ######## ######## main ########
version = '20210322' version = '20210329'
if (len(sys.argv) != 2): if (len(sys.argv) != 2):
print('Invalid Number of Arguments') print('Invalid Number of Arguments')
@ -577,7 +691,7 @@ if (sys.argv[1].strip() == '-v'):
print('YSFReflector version ' + version) print('YSFReflector version ' + version)
sys.exit() sys.exit()
## lettura configurazione ## ## reading configuration ##
config=[] config=[]
try: try:
ReadConfig(sys.argv[1].strip(), config) ReadConfig(sys.argv[1].strip(), config)

View File

@ -19,6 +19,8 @@ FilePath=/var/log
FileRoot=YSFReflector FileRoot=YSFReflector
# Set this to 0 and configure systems logrotate to do the job with a single log file # Set this to 0 and configure systems logrotate to do the job with a single log file
FileRotate=1 FileRotate=1
# Enable = 1 or disable = 0 the extended command set
EnableExtendedCommands=1
[Network] [Network]
Port=42395 Port=42395