Adding hooks for socket reporting.

NOT WORKING YET… but it is a start
This commit is contained in:
Cort Buffington 2018-06-19 16:02:38 -05:00
parent f9c4b78b45
commit df264042d6
4 changed files with 135 additions and 3 deletions

View File

@ -48,6 +48,7 @@ def build_config(_config_file):
CONFIG = {}
CONFIG['GLOBAL'] = {}
CONFIG['REPORTS'] = {}
CONFIG['LOGGER'] = {}
CONFIG['ALIASES'] = {}
CONFIG['AMBE'] = {}
@ -62,6 +63,14 @@ def build_config(_config_file):
'MAX_MISSED': config.getint(section, 'MAX_MISSED')
})
elif section == 'REPORTS':
CONFIG['REPORTS'].update({
'REPORT': config.getboolean(section, 'REPORT'),
'REPORT_INTERVAL': config.getint(section, 'REPORT_INTERVAL'),
'REPORT_PORT': config.getint(section, 'REPORT_PORT'),
'REPORT_CLIENTS': config.get(section, 'REPORT_CLIENTS').split(',')
})
elif section == 'LOGGER':
CONFIG['LOGGER'].update({
'LOG_FILE': config.get(section, 'LOG_FILE'),

View File

@ -9,6 +9,26 @@ PATH: ./
PING_TIME: 5
MAX_MISSED: 3
# NOT YET WORKING: NETWORK REPORTING CONFIGURATION
# Enabling "REPORT" will configure a socket-based reporting
# system that will send the configuration and other items
# to a another process (local or remote) that may process
# the information for some useful purpose, like a web dashboard.
#
# REPORT - True to enable, False to disable
# REPORT_INTERVAL - Seconds between reports
# REPORT_PORT - TCP port to listen on if "REPORT_NETWORKS" = NETWORK
# REPORT_CLIENTS - comma separated list of IPs you will allow clients
# to connect on. Entering a * will allow all.
#
[REPORTS]
REPORT: False
REPORT_INTERVAL: 60
REPORT_PORT: 4321
REPORT_CLIENTS: 127.0.0.1
# SYSTEM LOGGER CONFIGURAITON
# This allows the logger to be configured without chaning the individual
# python logger stuff. LOG_FILE should be a complete path/filename for *your*

View File

@ -39,15 +39,19 @@ from bitstring import BitArray
import socket
# Twisted is pretty important, so I keep it separate
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from twisted.internet import task
from twisted.internet.protocol import DatagramProtocol, Factory, Protocol
from twisted.protocols.basic import NetstringReceiver
from twisted.internet import reactor, task
# Other files we pull from -- this is mostly for readability and segmentation
import hb_log
import hb_config
from dmr_utils.utils import int_id, hex_str_4
# Imports for the reporting server
import cPickle as pickle
from reporting_const import *
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
__author__ = 'Cortney T. Buffington, N0MJS'
__copyright__ = 'Copyright (c) 2016 Cortney T. Buffington, N0MJS and the K0USY Group'
@ -60,6 +64,25 @@ __email__ = 'n0mjs@me.com'
# Global variables used whether we are a module or __main__
systems = {}
# Timed loop used for reporting IPSC status
#
# REPORT BASED ON THE TYPE SELECTED IN THE MAIN CONFIG FILE
def config_reports(_config, _logger, _factory):
if _config['REPORTS']['REPORT']:
def reporting_loop(_logger, _server):
_logger.debug('Periodic reporting loop started')
_server.send_config()
_logger.info('HBlink TCP reporting server configured')
report_server = _factory(_config, _logger)
report_server.clients = []
reactor.listenTCP(_config['REPORTS']['REPORT_PORT'], report_server)
reporting = task.LoopingCall(reporting_loop, _logger, report_server)
reporting.start(_config['REPORTS']['REPORT_INTERVAL'])
# Shut ourselves down gracefully by disconnecting from the masters and clients.
def hblink_handler(_signal, _frame, _logger):
for system in systems:
@ -469,6 +492,53 @@ class HBSYSTEM(DatagramProtocol):
else:
self._logger.error('(%s) Received an invalid command in packet: %s', self._system, ahex(_data))
#
# Socket-based reporting section
#
class report(NetstringReceiver):
def __init__(self, factory):
self._factory = factory
def connectionMade(self):
self._factory.clients.append(self)
self._factory._logger.info('HBlink reporting client connected: %s', self.transport.getPeer())
def connectionLost(self, reason):
self._factory._logger.info('HBlink reporting client disconnected: %s', self.transport.getPeer())
self._factory.clients.remove(self)
def stringReceived(self, data):
self.process_message(data)
def process_message(self, _message):
opcode = _message[:1]
if opcode == REPORT_OPCODES['CONFIG_REQ']:
self._factory._logger.info('HBlink reporting client sent \'CONFIG_REQ\': %s', self.transport.getPeer())
self.send_config()
else:
self._factory._logger.error('got unknown opcode')
class reportFactory(Factory):
def __init__(self, config, logger):
self._config = config
self._logger = logger
def buildProtocol(self, addr):
if (addr.host) in self._config['REPORTS']['REPORT_CLIENTS'] or '*' in self._config['REPORTS']['REPORT_CLIENTS']:
self._logger.debug('Permitting report server connection attempt from: %s:%s', addr.host, addr.port)
return report(self)
else:
self._logger.error('Invalid report server connection attempt from: %s:%s', addr.host, addr.port)
return None
def send_clients(self, _message):
for client in self.clients:
client.sendString(_message)
def send_config(self):
serialized = pickle.dumps(self._config['SYSTEMS'], protocol=pickle.HIGHEST_PROTOCOL)
self.send_clients(REPORT_OPCODES['CONFIG_SND']+serialized)
#************************************************
# MAIN PROGRAM LOOP STARTS HERE
@ -514,6 +584,9 @@ if __name__ == '__main__':
# Set signal handers so that we can gracefully exit if need be
for sig in [signal.SIGTERM, signal.SIGINT]:
signal.signal(sig, sig_handler)
# INITIALIZE THE REPORTING LOOP
config_reports(CONFIG, logger, reportFactory)
# HBlink instance creation
logger.info('HBlink \'HBlink.py\' (c) 2016 N0MJS & the K0USY Group - SYSTEM STARTING...')

30
reporting_const.py Normal file
View File

@ -0,0 +1,30 @@
###############################################################################
# Copyright (C) 2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
###############################################################################
# Opcodes for the network-based reporting protocol
REPORT_OPCODES = {
'CONFIG_REQ': '\x00',
'CONFIG_SND': '\x01',
'BRIDGE_REQ': '\x02',
'BRIDGE_SND': '\x03',
'CONFIG_UPD': '\x04',
'BRIDGE_UPD': '\x05',
'LINK_EVENT': '\x06',
'BRDG_EVENT': '\x07',
}