Ejemplo n.º 1
0
    async def _connect_coro(self):
        kwargs = dict()

        # Decode URI attributes
        uri_attributes = urlparse(self.session.broker_uri)
        scheme = uri_attributes.scheme
        secure = True if scheme in ("mqtts", "wss") else False
        self.session.username = (self.session.username if self.session.username
                                 else uri_attributes.username)
        self.session.password = (self.session.password if self.session.password
                                 else uri_attributes.password)
        self.session.remote_address = uri_attributes.hostname
        self.session.remote_port = uri_attributes.port
        if scheme in ("mqtt", "mqtts") and not self.session.remote_port:
            self.session.remote_port = 8883 if scheme == "mqtts" else 1883
        if scheme in ("ws", "wss") and not self.session.remote_port:
            self.session.remote_port = 443 if scheme == "wss" else 80
        if scheme in ("ws", "wss"):
            # Rewrite URI to conform to https://tools.ietf.org/html/rfc6455#section-3
            uri = (
                scheme,
                self.session.remote_address + ":" +
                str(self.session.remote_port),
                uri_attributes[2],
                uri_attributes[3],
                uri_attributes[4],
                uri_attributes[5],
            )
            self.session.broker_uri = urlunparse(uri)
        # Init protocol handler
        # if not self._handler:
        self._handler = ClientProtocolHandler(self.plugins_manager,
                                              loop=self._loop)

        if secure:
            sc = ssl.create_default_context(
                ssl.Purpose.SERVER_AUTH,
                cafile=self.session.cafile,
                capath=self.session.capath,
                cadata=self.session.cadata,
            )
            if "certfile" in self.config and "keyfile" in self.config:
                sc.load_cert_chain(self.config["certfile"],
                                   self.config["keyfile"])
            if "check_hostname" in self.config and isinstance(
                    self.config["check_hostname"], bool):
                sc.check_hostname = self.config["check_hostname"]
            kwargs["ssl"] = sc

        try:
            reader = None
            writer = None
            self._connected_state.clear()
            # Open connection
            if scheme in ("mqtt", "mqtts"):
                conn_reader, conn_writer = await asyncio.open_connection(
                    self.session.remote_address,
                    self.session.remote_port,
                    loop=self._loop,
                    **kwargs)
                reader = StreamReaderAdapter(conn_reader)
                writer = StreamWriterAdapter(conn_writer)
            elif scheme in ("ws", "wss"):
                websocket = await websockets.connect(
                    self.session.broker_uri,
                    subprotocols=["mqtt"],
                    loop=self._loop,
                    extra_headers=self.extra_headers,
                    **kwargs)
                reader = WebSocketsReader(websocket)
                writer = WebSocketsWriter(websocket)
            # Start MQTT protocol
            self._handler.attach(self.session, reader, writer)
            return_code = await self._handler.mqtt_connect()
            if return_code is not CONNECTION_ACCEPTED:
                self.session.transitions.disconnect()
                self.logger.warning("Connection rejected with code '%s'" %
                                    return_code)
                exc = ConnectException("Connection rejected by broker")
                exc.return_code = return_code
                raise exc
            else:
                # Handle MQTT protocol
                await self._handler.start()
                self.session.transitions.connect()
                self._connected_state.set()
                self.logger.debug(
                    "connected to %s:%s" %
                    (self.session.remote_address, self.session.remote_port))
            return return_code
        except InvalidURI as iuri:
            self.logger.warning("connection failed: invalid URI '%s'" %
                                self.session.broker_uri)
            self.session.transitions.disconnect()
            raise ConnectException(
                "connection failed: invalid URI '%s'" %
                self.session.broker_uri, iuri)
        except InvalidHandshake as ihs:
            self.logger.warning(
                "connection failed: invalid websocket handshake")
            self.session.transitions.disconnect()
            raise ConnectException(
                "connection failed: invalid websocket handshake", ihs)
        except (ProtocolHandlerException, ConnectionError, OSError) as e:
            self.logger.warning("MQTT connection failed: %r" % e)
            self.session.transitions.disconnect()
            raise ConnectException(e)
Ejemplo n.º 2
0
    def _connect_coro(self):
        sc = None
        reader = None
        writer = None
        kwargs = dict()

        # Decode URI attributes
        uri_attributes = urlparse(self.session.broker_uri)
        scheme = uri_attributes.scheme
        self.session.username = uri_attributes.username
        self.session.password = uri_attributes.password
        self.session.remote_address = uri_attributes.hostname
        self.session.remote_port = uri_attributes.port
        if scheme in ('mqtt', 'mqtts') and not self.session.remote_port:
            self.session.remote_port = 8883 if scheme == 'mqtts' else 1883

        if scheme in ('mqtts', 'wss'):
            if self.session.cafile is None or self.session.cafile == '':
                self.logger.warn(
                    "TLS connection can't be estabilshed, no certificate file (.cert) given"
                )
                raise ClientException(
                    "TLS connection can't be estabilshed, no certificate file (.cert) given"
                )
            sc = ssl.create_default_context(ssl.Purpose.SERVER_AUTH,
                                            cafile=self.session.cafile,
                                            capath=self.session.capath,
                                            cadata=self.session.cadata)
            if 'certfile' in self.config and 'keyfile' in self.config:
                sc.load_cert_chain(self.config['certfile'],
                                   self.config['keyfile'])
            kwargs['ssl'] = sc

        # Open connection
        try:
            if scheme in ('mqtt', 'mqtts'):
                conn_reader, conn_writer = \
                    yield from asyncio.open_connection(self.session.remote_address, self.session.remote_port, **kwargs)
                reader = StreamReaderAdapter(conn_reader)
                writer = StreamWriterAdapter(conn_writer)
            elif scheme in ('ws', 'wss'):
                websocket = yield from websockets.connect(
                    self.session.broker_uri, subprotocols=['mqtt'], **kwargs)
                reader = WebSocketsReader(websocket)
                writer = WebSocketsWriter(websocket)
        except Exception as e:
            self.logger.warn("connection failed: %s" % e)
            self.session.transitions.disconnect()
            raise ConnectException("connection Failed: %s" % e)

        return_code = None
        try:
            connect_packet = self.build_connect_packet()
            yield from connect_packet.to_stream(writer)
            self.logger.debug(" -out-> " + repr(connect_packet))

            connack = yield from ConnackPacket.from_stream(reader)
            self.logger.debug(" <-in-- " + repr(connack))
            return_code = connack.variable_header.return_code
        except Exception as e:
            self.logger.warn("connection failed: %s" % e)
            self.session.transitions.disconnect()
            raise ClientException("connection Failed: %s" % e)

        if return_code is not CONNECTION_ACCEPTED:
            yield from self._handler.stop()
            self.session.transitions.disconnect()
            self.logger.warn("Connection rejected with code '%s'" %
                             return_code)
            exc = ConnectException("Connection rejected by broker")
            exc.return_code = return_code
            raise exc
        else:
            # Handle MQTT protocol
            self._handler = ClientProtocolHandler(reader,
                                                  writer,
                                                  loop=self._loop)
            self._handler.attach_to_session(self.session)
            yield from self._handler.start()
            self.session.transitions.connect()
            self.logger.debug(
                "connected to %s:%s" %
                (self.session.remote_address, self.session.remote_port))
Ejemplo n.º 3
0
    def _connect_coro(self):
        kwargs = dict()

        # Decode URI attributes
        uri_attributes = urlparse(self.session.broker_uri)
        scheme = uri_attributes.scheme
        secure = True if scheme in ('mqtts', 'wss') else False
        self.session.username = uri_attributes.username
        self.session.password = uri_attributes.password
        self.session.remote_address = uri_attributes.hostname
        self.session.remote_port = uri_attributes.port
        if scheme in ('mqtt', 'mqtts') and not self.session.remote_port:
            self.session.remote_port = 8883 if scheme == 'mqtts' else 1883
        if scheme in ('ws', 'wss') and not self.session.remote_port:
            self.session.remote_port = 443 if scheme == 'wss' else 80
        if scheme in ('ws', 'wss'):
            # Rewrite URI to conform to https://tools.ietf.org/html/rfc6455#section-3
            uri = (scheme, self.session.remote_address + ":" +
                   str(self.session.remote_port), uri_attributes[2],
                   uri_attributes[3], uri_attributes[4], uri_attributes[5])
            self.session.broker_uri = urlunparse(uri)
        # Init protocol handler
        #if not self._handler:
        self._handler = ClientProtocolHandler(self.plugins_manager,
                                              loop=self._loop)

        if secure:
            if self.session.cafile is None or self.session.cafile == '':
                self.logger.warning(
                    "TLS connection can't be estabilshed, no certificate file (.cert) given"
                )
                raise ClientException(
                    "TLS connection can't be estabilshed, no certificate file (.cert) given"
                )
            sc = ssl.create_default_context(ssl.Purpose.SERVER_AUTH,
                                            cafile=self.session.cafile,
                                            capath=self.session.capath,
                                            cadata=self.session.cadata)
            if 'certfile' in self.config and 'keyfile' in self.config:
                sc.load_cert_chain(self.config['certfile'],
                                   self.config['keyfile'])
            if 'check_hostname' in self.config and isinstance(
                    self.config['check_hostname'], bool):
                sc.check_hostname = self.config['check_hostname']
            kwargs['ssl'] = sc

        try:
            reader = None
            writer = None
            self._connected_state.clear()
            # Open connection
            if scheme in ('mqtt', 'mqtts'):
                conn_reader, conn_writer = \
                    yield from asyncio.open_connection(
                        self.session.remote_address,
                        self.session.remote_port, loop=self._loop, **kwargs)
                reader = StreamReaderAdapter(conn_reader)
                writer = StreamWriterAdapter(conn_writer)
            elif scheme in ('ws', 'wss'):
                websocket = yield from websockets.connect(
                    self.session.broker_uri,
                    subprotocols=['mqtt'],
                    loop=self._loop,
                    **kwargs)
                reader = WebSocketsReader(websocket)
                writer = WebSocketsWriter(websocket)
            # Start MQTT protocol
            self._handler.attach(self.session, reader, writer)
            return_code = yield from self._handler.mqtt_connect()
            if return_code is not CONNECTION_ACCEPTED:
                self.session.transitions.disconnect()
                self.logger.warning("Connection rejected with code '%s'" %
                                    return_code)
                exc = ConnectException("Connection rejected by broker")
                exc.return_code = return_code
                raise exc
            else:
                # Handle MQTT protocol
                yield from self._handler.start()
                self.session.transitions.connect()
                self._connected_state.set()
                self.logger.debug(
                    "connected to %s:%s" %
                    (self.session.remote_address, self.session.remote_port))
            return return_code
        except InvalidURI as iuri:
            self.logger.warning("connection failed: invalid URI '%s'" %
                                self.session.broker_uri)
            self.session.transitions.disconnect()
            raise ConnectException(
                "connection failed: invalid URI '%s'" %
                self.session.broker_uri, iuri)
        except InvalidHandshake as ihs:
            self.logger.warning(
                "connection failed: invalid websocket handshake")
            self.session.transitions.disconnect()
            raise ConnectException(
                "connection failed: invalid websocket handshake", ihs)
        except (ProtocolHandlerException, ConnectionError, OSError) as e:
            self.logger.warning("MQTT connection failed: %r" % e)
            self.session.transitions.disconnect()
            raise ConnectException(e)
Ejemplo n.º 4
0
    async def _connect_coro(self):
        kwargs = dict()

        # Decode URI attributes
        uri_attributes = urlparse(self.session.broker_uri)
        scheme = uri_attributes.scheme
        secure = True if scheme in ('mqtts', 'wss') else False
        self.session.username = self.session.username if self.session.username else uri_attributes.username
        self.session.password = self.session.password if self.session.password else uri_attributes.password
        self.session.remote_address = uri_attributes.hostname
        self.session.remote_port = uri_attributes.port
        if scheme in ('mqtt', 'mqtts') and not self.session.remote_port:
            self.session.remote_port = 8883 if scheme == 'mqtts' else 1883
        if scheme in ('ws', 'wss') and not self.session.remote_port:
            self.session.remote_port = 443 if scheme == 'wss' else 80
        if scheme in ('ws', 'wss'):
            # Rewrite URI to conform to https://tools.ietf.org/html/rfc6455#section-3
            uri = (scheme, self.session.remote_address + ":" +
                   str(self.session.remote_port), uri_attributes[2],
                   uri_attributes[3], uri_attributes[4], uri_attributes[5])
            self.session.broker_uri = urlunparse(uri)
        # Init protocol handler
        #if not self._handler:
        self._handler = ClientProtocolHandler(self.plugins_manager)

        if secure:
            sc = ssl.create_default_context(ssl.Purpose.SERVER_AUTH,
                                            cafile=self.session.cafile,
                                            capath=self.session.capath,
                                            cadata=self.session.cadata)
            if 'certfile' in self.config and 'keyfile' in self.config:
                sc.load_cert_chain(self.config['certfile'],
                                   self.config['keyfile'])
            if 'check_hostname' in self.config and isinstance(
                    self.config['check_hostname'], bool):
                sc.check_hostname = self.config['check_hostname']
            kwargs['ssl_context'] = sc
            kwargs['autostart_tls'] = True

        try:
            adapter = None
            self._connected_state.clear()
            # Open connection
            if scheme in ('mqtt', 'mqtts'):
                conn = \
                    await anyio.connect_tcp(
                        self.session.remote_address,
                        self.session.remote_port, **kwargs)
                if secure:
                    await conn.start_tls()
                adapter = StreamAdapter(conn)
            elif scheme in ('ws', 'wss'):
                if kwargs.pop('autostart_tls', False):
                    kwargs['ssl'] = kwargs.pop('ssl_context')
                websocket = await create_websocket(self.session.broker_uri,
                                                   subprotocols=['mqtt'],
                                                   headers=self.extra_headers,
                                                   **kwargs)
                adapter = WebSocketsAdapter(websocket)
            # Start MQTT protocol
            await self._handler.attach(self.session, adapter)
            try:
                return_code = await self._handler.mqtt_connect()
            except NoDataException:
                self.logger.warning("Connection broken by broker")
                exc = ConnectException("Connection broken by broker")
                raise exc
            if return_code is not CONNECTION_ACCEPTED:
                self.session.transitions.disconnect()
                self.logger.warning("Connection rejected with code '%s'",
                                    return_code)
                exc = ConnectException("Connection rejected by broker")
                exc.return_code = return_code
                raise exc
            else:
                # Handle MQTT protocol
                await self._handler.start()
                self.session.transitions.connect()
                await self._connected_state.set()
                self.logger.debug("connected to %s:%s",
                                  self.session.remote_address,
                                  self.session.remote_port)
            return return_code
        except ProtocolError as exc:
            self.logger.warning(
                "connection failed: invalid websocket handshake")
            self.session.transitions.disconnect()
            raise ConnectException(
                "connection failed: invalid websocket handshake") from exc
        except (ProtocolHandlerException, ConnectionError, OSError) as exc:
            self.logger.warning("MQTT connection failed")
            self.session.transitions.disconnect()
            raise ConnectException from exc