def _init_common(self): """ Common initialization which needs to be done whether an object is created via `__init__` or `_init_from_config_file` is done in this method. """ self._validate_required_content() client_id = UuidGenerator.generate_id_as_string() # The number of times to retry during connect self._connect_retries = self._DEFAULT_CONNECT_RETRIES # The keep alive interval self._keep_alive_interval = self._DEFAULT_MQTT_KEEP_ALIVE_INTERVAL # The reconnect back off multiplier self._reconnect_back_off_multiplier = \ self._DEFAULT_RECONNECT_BACK_OFF_MULTIPLIER # The reconnect delay (in seconds) self._reconnect_delay = self._DEFAULT_RECONNECT_DELAY # The maximum reconnect delay self._reconnect_delay_max = self._DEFAULT_RECONNECT_DELAY_MAX # The reconnect delay random self._reconnect_delay_random = self._DEFAULT_RECONNECT_DELAY_RANDOM # Whether to reconnect when disconnected self._reconnect_when_disconnected = \ self._DEFAULT_RECONNECT_WHEN_DISCONNECTED # The unique identifier of the client self._client_id = client_id # Queue for getting the sorted broker list self._queue = None # The incoming message queue size self._incoming_message_queue_size = 1000 # The incoming thread pool size self._incoming_message_thread_pool_size = 1
def __init__(self, broker_ca_bundle, cert_file, private_key, brokers): """ Constructor parameters: :param broker_ca_bundle: The file name of a bundle containing the broker CA certificates in PEM format :param cert_file: The file name of the client certificate in PEM format :param private_key: The file name of the client private key in PEM format :param brokers: A list of :class:`dxlclient.broker.Broker` objects representing brokers comprising the DXL fabric. When invoking the :func:`dxlclient.client.DxlClient.connect` method, the :class:`dxlclient.client.DxlClient` will attempt to connect to the closest broker. """ super(DxlClientConfig, self).__init__() client_id = UuidGenerator.generate_id_as_string() if not broker_ca_bundle: raise ValueError("Broker CA bundle not specified") if not cert_file: raise ValueError("Certificate file not specified") if not private_key: raise ValueError("Private key file not specified") if brokers is None: raise ValueError("Brokers were not specified") # The number of times to retry during connect self._connect_retries = self._DEFAULT_CONNECT_RETRIES # The keep alive interval self._keep_alive_interval = self._DEFAULT_MQTT_KEEP_ALIVE_INTERVAL # The reconnect back off multiplier self._reconnect_back_off_multiplier = self._DEFAULT_RECONNECT_BACK_OFF_MULTIPLIER # The reconnect delay (in seconds) self._reconnect_delay = self._DEFAULT_RECONNECT_DELAY # The maximum reconnect delay self._reconnect_delay_max = self._DEFAULT_RECONNECT_DELAY_MAX # The reconnect delay random self._reconnect_delay_random = self._DEFAULT_RECONNECT_DELAY_RANDOM # Whether to reconnect when disconnected self._reconnect_when_disconnected = self._DEFAULT_RECONNECT_WHEN_DISCONNECTED # The unique identifier of the client self._client_id = client_id # The list of brokers self.brokers = brokers # The filename of the CA bundle file in PEM format self.broker_ca_bundle = broker_ca_bundle # The filename of the client certificate in PEM format (must not have a password) self.cert_file = cert_file # The filename of the private key used to request the certificates self.private_key = private_key # Queue for getting the sorted broker list self._queue = None # The incoming message queue size self._incoming_message_queue_size = 1000 # The incoming thread pool size self._incoming_message_thread_pool_size = 1
def __init__(self, tasks, thread_prefix): """ Constructs a ThreadPoolWorker. """ Thread.__init__(self) _ObjectTracker.get_instance().obj_constructed(self) self.tasks = tasks self.daemon = True self.name = thread_prefix + "-" + UuidGenerator.generate_id_as_string() self.start()
def __init__(self, client, service_type): """ Constructor parameters: :param client: The :class:`dxlclient.client.DxlClient` instance that will expose this service :param service_type: A textual name for the service. For example, "/mycompany/myservice" """ super(ServiceRegistrationInfo, self).__init__() # if not isinstance(channels, list): # raise ValueError('Channels should be a list') # if not channels: # raise InvalidServiceException('Channel list is empty') if not service_type: raise ValueError("Undefined service name") #The service type or name prefix self._service_type = service_type # The unique service ID self._service_id = UuidGenerator.generate_id_as_string() # The map of registered channels and their associated callbacks self._callbacks_by_topic = {} #The map of meta data associated with this service (name-value pairs) self._metadata = {} # List of destination tenants self._destination_tenant_guids = [] # The Time-To-Live (TTL) of the service registration (default: 60 minutes) self._ttl = 60 # minutes # The minimum Time-To-Live (TTL) of the service registration (default: 10 minutes) self._ttl_lower_limit = 10 # Internal client reference self._dxl_client = client # Registration sync object self._registration_sync = Condition() # Whether at least one registration has occurred self._registration_occurred = False # Whether at least one unregistration registration has occurred self._unregistration_occurred = False self._destroy_lock = RLock() self._destroyed = False
def __init__(self, destination_topic): """ Constructor parameters: :param destination_topic: The topic to publish the message to """ super(Message, self).__init__() ########### # Version 0 ########### # The version of the message self._version = self.MESSAGE_VERSION # The unique identifier for the message self._message_id = UuidGenerator.generate_id_as_string() # The identifier for the client that is the source of the message self._source_client_id = "" # The GUID for the broker that is the source of the message self._source_broker_id = "" # The channel that the message is published on self._destination_topic = destination_topic # The payload to send with the message self._payload = bytes() # The set of broker GUIDs to deliver the message to self._broker_ids = [] # The set of client GUIDs to deliver the message to self._client_ids = [] ########### # Version 1 ########### # Other fields: way to add fields to message types self._other_fields = {} ########### # Version 2 ########### # The GUID for the tenant that is the source of the message self._source_tenant_guid = "" # The set of tenant GUIDs to deliver the message to self._destination_tenant_guids = []
def _update_broker_config_model(self): """ Set the contents of :meth:`brokers` into the configobj model, converting the list of :class:`dxlclient.broker.Broker` objects into a `dict` matching the format needed for the dxlclient config file. """ brokers = self.brokers if brokers is None: self._set_value_to_config(self._BROKERS_SECTION, None) else: brokers_for_config = OrderedDict() # A `unique_id` is not required for the in-memory representation of # a `Broker` object but it effectively is required when persisting # the broker configuration to a file. If no `unique_id` is found # on the `Broker` object, assign a random one as the key for the # broker config section so that the file can at least be persisted. for broker in brokers: unique_id = broker.unique_id if broker.unique_id else \ UuidGenerator.generate_id_as_string() brokers_for_config[unique_id] = broker._to_broker_string() # In order to attempt to preserve any comments that may have been # added to the configuration file for a pre-existing broker, this # code preserves the `configobj` model objects which already # exist for the brokers being set. current_brokers = self._get_value_from_config( self._BROKERS_SECTION) brokers_to_delete = [] for current_broker_key in current_brokers.keys(): if current_broker_key not in brokers_for_config: brokers_to_delete.append(current_broker_key) # `configobj` model entries not present in the brokers to be set # are deleted - along with any associated comments. for broker_to_delete in brokers_to_delete: del current_brokers[broker_to_delete] # The `merge` updates the values for pre-existing keys and adds in # new key/value pairs which are not already present in the config # model. current_brokers.merge(brokers_for_config)
def parse(broker_url): """ Returns a broker instance corresponding to the specified broker URL of the form: ``[ssl://]<hostname>[:port]`` Valid URLs include: - ``ssl://mybroker:8883`` - ``ssl://mybroker`` - ``mybroker:8883`` - ``mybroker`` If the port is omitted it will be defaulted to 8883. :param broker_url: A valid broker URL :return: A broker corresponding to the specified broker URL """ broker = Broker(host_name='none') elements = broker_url.split("://") host_name = broker_url protocol = Broker._SSL_PROTOCOL port = Broker._SSL_PORT if len(elements) == 2: protocol = elements[0] host_name = elements[1] if host_name[-1] != ']': host_name_left, _, host_name_right = host_name.rpartition(":") if host_name_left: host_name = host_name_left port = host_name_right broker.host_name = host_name broker.port = port broker.unique_id = UuidGenerator.generate_id_as_string() if protocol and protocol.lower() != Broker._SSL_PROTOCOL.lower(): raise MalformedBrokerUriException("Unknown protocol: " + protocol) return broker
def __init__(self, config): """ Constructor parameters: :param config: The :class:`dxlclient.client_config.DxlClientConfig` object containing the configuration settings for the client. """ super(DxlClient, self).__init__() if config is None or not isinstance(config, DxlClientConfig): raise ValueError("Client configuration not specified") # The client configuration self._config = config # The lock for the client configuration self._config_lock = threading.RLock() # The condition associated with the client configuration self._config_lock_condition = threading.Condition(self._config_lock) # The flag for the connection state self._connected = False # The lock for the flag for the connection state self._connected_lock = threading.RLock() # The condition for the flag on connection state self._connected_wait_condition = threading.Condition( self._connected_lock) # The current broker the client is connected to self._current_broker = None # The lock for the current broker the client is connected to self._current_broker_lock = threading.RLock() # The default wait time for a synchronous request self._default_wait = self._DEFAULT_WAIT # The wait for policy delay (in seconds) self._wait_for_policy_delay = self._DEFAULT_WAIT_FOR_POLICY_DELAY # The minimum amount of threads in a thread pool self._core_pool_size = self._DEFAULT_MIN_POOL_SIZE # The maximum amount of threads in a thread pool self._maximum_pool_size = self._DEFAULT_MAX_POOL_SIZE # The quality of server (QOS) for messages self._qos = self._DEFAULT_QOS # The "reply-to" prefix. self is typically used for setting up response # channels for requests, etc. self._reply_to_topic = self._REPLY_TO_PREFIX + self._config._client_id # The request callbacks manager self._request_callbacks = callback_manager._RequestCallbackManager() # The response callbacks manager self._response_callbacks = callback_manager._ResponseCallbackManager() # The event callbacks manager self._event_callbacks = callback_manager._EventCallbackManager() # The current list of subscriptions self._subscriptions = set() # The lock for the current list of subscriptions self._subscriptions_lock = threading.RLock() # The underlying MQTT client instance self._client = mqtt.Client(client_id=self._config._client_id, clean_session=True, userdata=self, protocol=mqtt.MQTTv31) # The MQTT client connect callback self._client.on_connect = _on_connect # The MQTT client disconnect callback self._client.on_disconnect = _on_disconnect # The MQTT client message callback self._client.on_message = _on_message # The MQTT client log callback if logger.isEnabledFor(logging.DEBUG): self._client.on_log = _on_log # pylint: disable=no-member # The MQTT client TLS configuration self._client.tls_set(config.broker_ca_bundle, certfile=config.cert_file, keyfile=config.private_key, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_SSLv23, ciphers=None) # The MQTT client TLS configuration to bypass hostname validation self._client.tls_insecure_set(True) # Generate a message pool prefix self._message_pool_prefix = "DxlMessagePool-" + UuidGenerator.generate_id_as_string( ) # The thread pool for message handling self._thread_pool = ThreadPool( num_threads=config.incoming_message_thread_pool_size, queue_size=config.incoming_message_queue_size, thread_prefix=self._message_pool_prefix) # Subscribe to the client reply channel self.subscribe(self._reply_to_topic) # The request manager (manages synchronous and asynchronous request callbacks, # notifications, etc.). self._request_manager = RequestManager(client=self) # The service manager (manages services request callbacks, notifications, etc.). self._service_manager = _ServiceManager(client=self) # The loop thread self._thread = None # The loop thread terminate flag self._thread_terminate = False # The lock for the connect thread self._connect_wait_lock = threading.RLock() # The condition associated with the client configuration self._connect_wait_condition = threading.Condition( self._connect_wait_lock) self._destroy_lock = threading.RLock() self._destroyed = False