4949 pubCallbacks: Table [string , TopicCb ]
5050 inWork: bool
5151 hasNewWorks: bool
52- keepAlive: uint16
52+ keepAlive: Duration
53+ keepAliveTimeout: Duration
54+ keepAliveMonitorRunned: bool
5355 pingRunned: bool
5456 lastSend: MonoTime
5557 awaitingPingResp: bool
6769 version: uint8
6870 connFlags: string
6971 subscribed: Table [string , QoS ] # Topic, QoS
70- lastAction: float # Check keepAlive
72+ lastAction: MonoTime # Check keepAlive
7173
7274 # when defined(broker):
7375 ConnAckFlag = enum
@@ -324,7 +326,7 @@ proc splitTopic(topic: string): seq[string] =
324326
325327when defined (broker):
326328 proc retainMsg (topic: string , message: string , qos: QoS , clientid: string ) =
327- mqttbroker.retained[topic] = RetainedMsg (msg: message, qos: qos, time: epochTime (), clientid: clientid)
329+ mqttbroker.retained[topic] = RetainedMsg (msg: message, qos: qos, clientid: clientid)
328330
329331when defined (broker):
330332 proc addSubscriber * (ctx: MqttCtx , topic: string ) {.async .} =
@@ -519,7 +521,7 @@ proc sendConnect(ctx: MqttCtx): Future[bool] =
519521 pkt.put (" MQTT" , true )
520522 pkt.put (4 .uint8 )
521523 pkt.put (flags)
522- pkt.put (ctx.keepAlive)
524+ pkt.put (uint16 ( ctx.keepAlive.inSeconds) )
523525 pkt.put (ctx.clientId, true )
524526
525527 if ctx.willFlag:
@@ -715,14 +717,19 @@ proc work(ctx: MqttCtx) {.async.} =
715717when defined (broker):
716718 proc sendWill (ctx: MqttCtx ) {.async .} =
717719 # # Send the will
718- if ctx.willTopic != " " :
719- if ctx.willRetain:
720- retainMsg (ctx.willTopic, ctx.willMsg, ctx.willQoS, ctx.clientid)
721- for c in mqttbroker.subscribers[ctx.willTopic].ctxs:
722- let msgId = c.nextMsgId ()
723- let qos = qosAlign (ctx.willQoS, c.subscribed[ctx.willTopic])
724- c.workQueue[msgId] = Work (wk: PubWork , msgId: msgId, topic: ctx.willTopic, qos: qos, retain: ctx.willRetain, message: ctx.willMsg, typ: Publish )
725- await c.work ()
720+ if not ctx.willFlag:
721+ return
722+ if ctx.willRetain:
723+ retainMsg (ctx.willTopic, ctx.willMsg, ctx.willQoS, ctx.clientid)
724+
725+ if not mqttbroker.subscribers.hasKey (ctx.willTopic):
726+ return
727+ for c in mqttbroker.subscribers[ctx.willTopic].ctxs:
728+ let msgId = c.nextMsgId ()
729+ let qos = qosAlign (ctx.willQoS, c.subscribed[ctx.willTopic])
730+ c.workQueue[msgId] = Work (wk: PubWork , msgId: msgId, topic: ctx.willTopic, qos: qos,
731+ retain: ctx.willRetain, message: ctx.willMsg, typ: Publish )
732+ await c.work ()
726733
727734when defined (broker):
728735 proc publishToSubscribers (seqctx: seq [MqttCtx ], pkt: Pkt , matchedTopic, topic, message: string , qos: QoS , retain: bool , senderId: string ) {.async .} =
@@ -756,19 +763,24 @@ proc onConnect(ctx: MqttCtx, pkt: Pkt) {.async.} =
756763 var
757764 offset: int
758765 nextLen: uint16
766+ keepAlive: uint16
759767
760768 # Main data
761769 (ctx.proto, offset) = pkt.getstring (0 , true )
762770 (ctx.version, offset) = pkt.getu8 (offset)
763771 (ctx.connFlags, offset) = getbin (pkt, offset)
764- (ctx.keepAlive, offset) = pkt.getu16 (offset)
772+ (keepAlive, offset) = pkt.getu16 (offset)
773+ ctx.keepAlive = initDuration (seconds = int64 (keepAlive))
774+ ctx.keepAliveTimeout = initDuration (milliseconds = int64 (float (ctx.keepAlive.inMilliseconds) * 1.5 ))
765775 (nextLen, offset) = pkt.getu16 (offset)
766776 (ctx.clientId, offset) = pkt.getstring (offset, parseInt ($ nextLen))
767777 if not mqttbroker.spacesInClientId:
768778 ctx.clientid = ctx.clientid.replace (" " , " " )
769779
770780 # Will Topic
771- if ctx.connFlags[5 ] == '1' :
781+ ctx.willFlag = ctx.connFlags[5 ] == '1'
782+ if ctx.willFlag:
783+ ctx.willFlag = true
772784 (nextLen, offset) = pkt.getu16 (offset)
773785 (ctx.willTopic, offset) = pkt.getstring (offset, parseInt ($ nextLen))
774786 (nextLen, offset) = pkt.getu16 (offset)
@@ -1058,8 +1070,6 @@ proc onDisconnect(ctx: MqttCtx, pkt: Pkt) {.async.} =
10581070 when not defined (broker):
10591071 ctx.wrn (" Packet type only supported for broker: " & $ pkt.typ)
10601072 else :
1061- # await removeSubscriber(ctx)
1062- # await sendWill(ctx)
10631073 ctx.state = Disconnected
10641074 if mqttbroker.verbosity >= 1 :
10651075 verbose (" Connections >> " & ctx.clientid & " has disconnected" )
@@ -1080,7 +1090,7 @@ proc onPingResp(ctx: MqttCtx, pkt: Pkt) {.async.} =
10801090
10811091proc handle (ctx: MqttCtx , pkt: Pkt ) {.async .} =
10821092 when defined (broker):
1083- ctx.lastAction = epochTime ()
1093+ ctx.lastAction = getMonoTime ()
10841094
10851095 case pkt.typ
10861096 of ConnAck : await ctx.onConnAck (pkt)
@@ -1120,30 +1130,38 @@ proc runPing(ctx: MqttCtx) {.async.} =
11201130 return
11211131 ctx.pingRunned = true
11221132 while true :
1123- await sleepAsync (1000 )
1124-
11251133 if ctx.state notin {Connecting , Connected , Disconnecting }:
11261134 break
11271135 if ctx.state != Connected :
1136+ await sleepAsync (500 )
11281137 continue
11291138
11301139 let now = getMonoTime ()
11311140 if ctx.awaitingPingResp:
11321141 if now >= ctx.timeoutPingRespTime:
11331142 await ctx.close (" ping response timeout" )
11341143 break
1144+ await sleepAsync (500 )
1145+
1146+ else :
1147+ let ms = (ctx.keepAlive - (now - ctx.lastSend)).inMilliseconds
1148+ if ms < 0 :
1149+ discard await ctx.sendPingReq ()
1150+ ctx.timeoutPingRespTime = now + ctx.pingRespTimeout
1151+ ctx.awaitingPingResp = true
11351152
1136- elif (now - ctx.lastSend).inSeconds >= int64 (ctx.keepAlive):
1137- discard await ctx.sendPingReq ()
1138- ctx.timeoutPingRespTime = now + ctx.pingRespTimeout
1139- ctx.awaitingPingResp = true
1153+ elif ms < 1000 :
1154+ await sleepAsync (int (ms))
1155+
1156+ else :
1157+ await sleepAsync (1000 )
11401158
11411159 ctx.pingRunned = false
11421160
11431161proc connectBroker (ctx: MqttCtx ) {.async .} =
11441162 # # Connect to the broker.
1145- if ctx.keepAlive == 0 :
1146- ctx.keepAlive = 60
1163+ if ctx.keepAlive == DurationZero :
1164+ ctx.keepAlive = initDuration (seconds = 60 )
11471165
11481166 if ctx.verbosity >= 1 :
11491167 ctx.dbg (" Connecting to " & ctx.host & " :" & $ ctx.port)
@@ -1206,12 +1224,12 @@ proc runConnect(ctx: MqttCtx) {.async.} =
12061224proc newMqttCtx * (clientId: string ): MqttCtx =
12071225 # # Initiate a new MQTT client.
12081226 MqttCtx (clientId: clientId, state: Disconnected , maxInflightMessages: 20 ,
1209- keepAlive: 60 , pingRespTimeout: initDuration (seconds = 10 ))
1227+ keepAlive: initDuration (seconds = 60 ) , pingRespTimeout: initDuration (seconds = 10 ))
12101228
12111229proc setPingInterval * (ctx: MqttCtx , txInterval: int = 60 ) =
12121230 # # Set the clients ping interval in seconds. Default is 60 seconds.
12131231 if txInterval > 0 and txInterval < 65535 :
1214- ctx.keepAlive = txInterval. uint16
1232+ ctx.keepAlive = initDuration (seconds = int64 ( txInterval))
12151233
12161234proc setHost * (ctx: MqttCtx , host: string , port: int = 1883 , sslOn = false ) =
12171235 # # Set the MQTT host.
0 commit comments