Line data Source code
1 : /*
2 : * Package : mqtt_client
3 : * Author : S. Hamblett <steve.hamblett@linux.com>
4 : * Date : 22/06/2017
5 : * Copyright : S.Hamblett
6 : */
7 :
8 : part of mqtt_client;
9 :
10 : /// Connection handler that performs connections and disconnections to the hostname in a synchronous manner.
11 : class SynchronousMqttConnectionHandler extends MqttConnectionHandler
12 : with events.EventDetector {
13 : /// Max connection attempts
14 : static const int maxConnectionAttempts = 3;
15 :
16 : /// Synchronously connect to the specific Mqtt Connection.
17 : Future<ConnectionState> internalConnect(String hostname, int port,
18 : MqttConnectMessage connectMessage) async {
19 : int connectionAttempts = 0;
20 3 : MqttLogger.log("SynchronousMqttConnectionHandler::internalConnect entered");
21 : do {
22 : // Initiate the connection
23 3 : MqttLogger.log(
24 3 : "SynchronousMqttConnectionHandler::internalConnect - initiating connection try $connectionAttempts");
25 3 : connectionState = ConnectionState.connecting;
26 3 : if (useWebSocket) {
27 1 : MqttLogger.log(
28 : "SynchronousMqttConnectionHandler::internalConnect - websocket selected");
29 2 : connection = new MqttWsConnection();
30 2 : } else if (secure) {
31 1 : MqttLogger.log(
32 : "SynchronousMqttConnectionHandler::internalConnect - secure selected");
33 1 : connection =
34 3 : new MqttSecureConnection(trustedCertPath, privateKeyFilePath);
35 : } else {
36 1 : MqttLogger.log(
37 : "SynchronousMqttConnectionHandler::internalConnect - insecure TCP selected");
38 2 : connection = new MqttNormalConnection();
39 : }
40 9 : await connection.connect(hostname, port);
41 6 : this.registerForMessage(MqttMessageType.connectAck, _connectAckProcessor);
42 9 : this.listen(connection, MessageAvailable, this.messageAvailable);
43 : // Transmit the required connection message to the broker.
44 3 : MqttLogger.log(
45 : "SynchronousMqttConnectionHandler::internalConnect sending connect message");
46 3 : sendMessage(connectMessage);
47 3 : MqttLogger.log(
48 6 : "SynchronousMqttConnectionHandler::internalConnect - pre sleep, state = $connectionState");
49 : // We're the sync connection handler so we need to wait for the brokers acknowledgement of the connections
50 6 : await MqttUtilities.asyncSleep(5);
51 3 : MqttLogger.log(
52 6 : "SynchronousMqttConnectionHandler::internalConnect - post sleep, state = $connectionState");
53 6 : } while (connectionState != ConnectionState.connected &&
54 0 : ++connectionAttempts < maxConnectionAttempts);
55 : // If we've failed to handshake with the broker, throw an exception.
56 6 : if (connectionState != ConnectionState.connected) {
57 : MqttLogger
58 0 : .log("SynchronousMqttConnectionHandler::internalConnect failed");
59 0 : throw new NoConnectionException(
60 : "The maximum allowed connection attempts ({$maxConnectionAttempts}) were exceeded. "
61 : "The broker is not responding to the connection request message "
62 : "(Missing Connection Acknowledgement");
63 : }
64 3 : MqttLogger.log(
65 6 : "SynchronousMqttConnectionHandler::internalConnect exited with state $connectionState");
66 3 : return connectionState;
67 1 : }
68 :
69 : ConnectionState disconnect() {
70 3 : MqttLogger.log("SynchronousMqttConnectionHandler::disconnect");
71 : // Send a disconnect message to the broker
72 3 : connectionState = ConnectionState.disconnecting;
73 6 : sendMessage(new MqttDisconnectMessage());
74 3 : this.ignoreAllEvents();
75 3 : _performConnectionDisconnect();
76 3 : return connectionState = ConnectionState.disconnected;
77 : }
78 :
79 : /// Disconnects the underlying connection object.
80 : void _performConnectionDisconnect() {
81 : // Set the connection to disconnected.
82 6 : connection.disconnectRequested = true;
83 3 : connectionState = ConnectionState.disconnected;
84 : }
85 :
86 : /// Processes the connect acknowledgement message.
87 : bool _connectAckProcessor(MqttMessage msg) {
88 3 : MqttLogger.log("SynchronousMqttConnectionHandler::_connectAckProcessor");
89 : try {
90 3 : final MqttConnectAckMessage ackMsg = msg as MqttConnectAckMessage;
91 : // Drop the connection if our connect request has been rejected.
92 9 : if (ackMsg.variableHeader.returnCode ==
93 : MqttConnectReturnCode.brokerUnavailable ||
94 9 : ackMsg.variableHeader.returnCode ==
95 : MqttConnectReturnCode.identifierRejected ||
96 9 : ackMsg.variableHeader.returnCode ==
97 : MqttConnectReturnCode.unacceptedProtocolVersion ||
98 9 : ackMsg.variableHeader.returnCode ==
99 : MqttConnectReturnCode.notAuthorized ||
100 9 : ackMsg.variableHeader.returnCode ==
101 : MqttConnectReturnCode.badUsernameOrPassword) {
102 0 : MqttLogger.log(
103 : "SynchronousMqttConnectionHandler::_connectAckProcessor connection rejected");
104 0 : _performConnectionDisconnect();
105 : } else {
106 : // Initialize the keepalive to start the ping based keepalive process.
107 3 : MqttLogger.log(
108 : "SynchronousMqttConnectionHandler::_connectAckProcessor - state = connected");
109 3 : connectionState = ConnectionState.connected;
110 : }
111 : } catch (InvalidMessageException) {
112 0 : _performConnectionDisconnect();
113 : }
114 : return true;
115 : }
116 : }
|