Source code for secsgem.hsms.connectionmanager

#####################################################################
# connectionmanager.py
#
# (c) Copyright 2013-2015, Benjamin Parzella. All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This software 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 Lesser General Public License for more details.
#####################################################################
"""Contains class for handling multiple connections."""

import logging

from secsgem.common import EventProducer

from handler import HsmsHandler
from connections import HsmsMultiPassiveServer


[docs]class HsmsConnectionManager(EventProducer): """High level class that handles multiple active and passive connections and the model for them. :param event_handler: object for event handling :type event_handler: :class:`secsgem.common.EventHandler` """ def __init__(self, event_handler=None): EventProducer.__init__(self, event_handler) self.logger = logging.getLogger(self.__module__ + "." + self.__class__.__name__) self.handlers = {} self.servers = {} self.stopping = False
[docs] def has_connection_to(self, index): """Check if connection to certain peer exists. :param index: Name of the reqested handler. :type index: string :returns: Is peer available :rtype: boolean """ for handlerID in self.handlers.keys(): handler = self.handlers[handlerID] if handler.name == index: return handler return None
def __getitem__(self, index): for handlerID in self.handlers.keys(): handler = self.handlers[handlerID] if handler.name == index: return handler return None @staticmethod
[docs] def get_connection_id(address): """Generates connection ids used for internal indexing. :param address: The IP address for the affected remote. :type address: string """ return "%s" % address
def _update_required_servers(self, additional_port=-1): """Starts server if any active handler is found .. warning:: Do not call this directly, for internal use only. """ required_ports = [] if additional_port > 0: required_ports.append(additional_port) for handlerID in self.handlers.keys(): handler = self.handlers[handlerID] if not handler.active: if handler.port not in required_ports: required_ports.append(handler.port) for serverPort in self.servers.keys(): if serverPort not in required_ports: self.logger.debug("stopping server on port {0}".format(serverPort)) self.servers[serverPort].stop() del self.servers[serverPort] for requiredPort in required_ports: if requiredPort not in self.servers: self.logger.debug("starting server on port {0}".format(requiredPort)) self.servers[requiredPort] = HsmsMultiPassiveServer(requiredPort) self.servers[requiredPort].start() def _on_event(self, event_name, data): """Callback function for disconnection event :param event_name: Name of the event :type event_name: string :param data: Data supplied with event :type data: dict .. warning:: Do not call this directly, for internal use only. """ connection = data['connection'] connection_id = self.get_connection_id(connection.remoteIP) if connection_id in self.handlers.keys(): data['handler'] = self.handlers[connection_id] self.fire_event(event_name, data)
[docs] def add_peer(self, name, address, port, active, session_id, connection_handler=HsmsHandler): """Add a new connection :param name: Name of the peers configuration :type name: string :param address: IP address of peer :type address: string :param port: TCP port of peer :type port: integer :param active: Is the connection active (*True*) or passive (*False*) :type active: boolean :param session_id: session / device ID of peer :type session_id: integer :param connection_handler: Model handling this connection :type connection_handler: inherited from :class:`secsgem.hsms.handler.HsmsHandler` """ self.logger.debug("new remote %s at %s:%d", name, address, port) connection_id = self.get_connection_id(address) self._update_required_servers(port) if active: handler = connection_handler(address, port, active, session_id, name, self.parentEventHandler) else: handler = connection_handler(address, port, active, session_id, name, self.parentEventHandler, self.servers[port]) handler.enable() self.handlers[connection_id] = handler return handler
[docs] def remove_peer(self, name, address, port): """Remove a previously added connection :param name: Name of the peers configuration :type name: string :param address: IP address of peer :type address: string :param port: TCP port of peer :type port: integer """ self.logger.debug("disconnecting from %s at %s:%d", name, address, port) connection_id = self.get_connection_id(address) if connection_id in self.handlers.keys(): handler = self.handlers[connection_id] handler.connection.disconnect() handler.disable() del self.handlers[connection_id] self._update_required_servers()
[docs] def stop(self): """Stop all servers and terminate the connections""" self.stopping = True for handlerID in self.handlers.keys(): handler = self.handlers[handlerID] handler.connection.disconnect() self.handlers.clear() self._update_required_servers()