@@ -124,23 +124,6 @@ func NewMqttEngine(creator, clientid string, pubsub uint8, statusch chan Compone
124124 // me.Cancel is used to tell the paho connection manager to stop
125125 ctx , me .Cancel = context .WithCancel (context .Background ())
126126
127- var subs []paho.SubscribeOptions
128- if me .CanSubscribe {
129- nolocal := false
130- for topic , data := range me .TopicData {
131- // if data.ValidatorKey != nil {
132- if data .SubMode != "" {
133- lg .Printf ("MQTT Engine: subscribing to topic %s with mode %s, qos: %d" , topic , data .SubMode , me .QoS )
134- subs = append (subs , paho.SubscribeOptions {Topic : topic , QoS : byte (me .QoS ), NoLocal : nolocal })
135- }
136- }
137-
138- // log.Printf("MQTT Engine: there are %d topics to subscribe to", len(subs))
139- // for _, v := range subs {
140- // lg.Printf("MQTT Engine: subscribing to topic %s", v.Topic)
141- // }
142- }
143-
144127 apcConfig := autopaho.ClientConfig {
145128 ServerUrls : []* url.URL {serverURL },
146129 TlsCfg : & tls.Config {
@@ -153,6 +136,26 @@ func NewMqttEngine(creator, clientid string, pubsub uint8, statusch chan Compone
153136 SessionExpiryInterval : 60 ,
154137 OnConnectionUp : func (cm * autopaho.ConnectionManager , connAck * paho.Connack ) {
155138 lg .Printf ("MQTT Engine %s: MQTT connection up" , me .Creator )
139+
140+ var subs []paho.SubscribeOptions
141+ if me .CanSubscribe {
142+ nolocal := false
143+ me .DataMu .Lock ()
144+ for topic , data := range me .TopicData {
145+ // if data.ValidatorKey != nil {
146+ if data .SubMode != "" {
147+ lg .Printf ("MQTT Engine: subscribing to topic %s with mode %s, qos: %d" , topic , data .SubMode , me .QoS )
148+ subs = append (subs , paho.SubscribeOptions {Topic : topic , QoS : byte (me .QoS ), NoLocal : nolocal })
149+ }
150+ }
151+ me .DataMu .Unlock ()
152+
153+ // log.Printf("MQTT Engine: there are %d topics to subscribe to", len(subs))
154+ // for _, v := range subs {
155+ // lg.Printf("MQTT Engine: subscribing to topic %s", v.Topic)
156+ // }
157+ }
158+
156159 if subs != nil {
157160 lg .Printf ("MQTT Engine %s: subscribing to topics: %v" , me .Creator , subs )
158161 sa , err := cm .Subscribe (context .Background (), & paho.Subscribe {
@@ -309,6 +312,7 @@ func NewMqttEngine(creator, clientid string, pubsub uint8, statusch chan Compone
309312 }
310313
311314 var payload []byte
315+ me .DataMu .Lock ()
312316 td := me .TopicData [outbox .Topic ]
313317 // signingkey := me.SigningKeys[outbox.Topic]
314318 if td .Sign {
@@ -329,6 +333,7 @@ func NewMqttEngine(creator, clientid string, pubsub uint8, statusch chan Compone
329333 payload = buf .Bytes ()
330334 lg .Printf ("MQTT Engine %s: not signing raw message being sent to topic %s" , me .Creator , outbox .Topic )
331335 }
336+ me .DataMu .Unlock ()
332337
333338 mqttMsg := paho.Publish {
334339 Topic : outbox .Topic ,
@@ -345,9 +350,11 @@ func NewMqttEngine(creator, clientid string, pubsub uint8, statusch chan Compone
345350 fmt .Printf ("MQTT Engine %s: publish qos: %d, response: %+v\n " , me .Creator , me .QoS , pubresponse )
346351 dump .P (pubresponse )
347352
353+ me .DataMu .Lock ()
348354 td .PubMsgs ++
349355 td .LatestPub = time .Now ()
350356 me .TopicData [outbox .Topic ] = td
357+ me .DataMu .Unlock ()
351358 if GlobalCF .Debug {
352359 lg .Printf ("MQTT Engine %s: sent message on topic %s: %s" , me .Creator , outbox .Topic , string (payload ))
353360 }
@@ -365,18 +372,21 @@ func NewMqttEngine(creator, clientid string, pubsub uint8, statusch chan Compone
365372 lg .Printf ("MQTT Engine %s: error fetching topic data for topic %s: %v" , me .Creator , inbox .Packet .Topic , err )
366373 continue
367374 }
375+ me .DataMu .Lock ()
368376 td .SubMsgs ++
369377 td .LatestSub = time .Now ()
378+ validate := td .Validate
379+ subCh := td .SubscriberCh
370380 me .TopicData [td .Topic ] = td
381+ me .DataMu .Unlock ()
371382
372383 mpi := MqttPkgIn {
373384 TimeStamp : time .Now (),
374385 Topic : inbox .Packet .Topic ,
375386 Payload : inbox .Packet .Payload ,
376387 Validated : false ,
377388 }
378-
379- if td .Validate {
389+ if validate {
380390 payload , err := jws .Verify (inbox .Packet .Payload , jws .WithKeySet (me .Keystore ))
381391 if err != nil {
382392 mpi .Error = true
@@ -392,9 +402,9 @@ func NewMqttEngine(creator, clientid string, pubsub uint8, statusch chan Compone
392402 } else {
393403 lg .Printf ("MQTT Engine %s: unvalidated message: %s" , me .Creator , inbox .Packet .Payload )
394404 }
395- lg .Printf ("MQTT Engine td.SubscriberCh: %+v" , td . SubscriberCh )
396- if td . SubscriberCh != nil {
397- td . SubscriberCh <- mpi
405+ lg .Printf ("MQTT Engine td.SubscriberCh: %+v" , subCh )
406+ if subCh != nil {
407+ subCh <- mpi
398408 } else {
399409 lg .Printf ("MQTT Engine %s: no subscriber channel for topic %s. Dropping message." , me .Creator , inbox .Packet .Topic )
400410 }
@@ -421,18 +431,19 @@ func NewMqttEngine(creator, clientid string, pubsub uint8, statusch chan Compone
421431 return & me , nil
422432}
423433
424- func (me * MqttEngine ) PubToTopic (topic string , signingkey * ecdsa.PrivateKey , mode string , sign bool ) ( map [ string ] TopicData , error ) {
434+ func (me * MqttEngine ) PubToTopic (topic string , signingkey * ecdsa.PrivateKey , mode string , sign bool ) error {
425435 if topic == "" {
426- return me . TopicData , fmt .Errorf ("PubToTopic: topic not specified" )
436+ return fmt .Errorf ("PubToTopic: topic not specified" )
427437 }
428438 if signingkey == nil && sign {
429- return me . TopicData , fmt .Errorf ("PubToTopic: no signing key specified and signing requested" )
439+ return fmt .Errorf ("PubToTopic: no signing key specified and signing requested" )
430440 }
431441
432442 if mode != "raw" && mode != "struct" {
433- return me . TopicData , fmt .Errorf ("PubToTopic: unknown mode: %s" , mode )
443+ return fmt .Errorf ("PubToTopic: unknown mode: %s" , mode )
434444 }
435445
446+ me .DataMu .Lock ()
436447 if _ , exist := me .TopicData [topic ]; ! exist {
437448 me .TopicData [topic ] = TopicData {}
438449 }
@@ -447,6 +458,8 @@ func (me *MqttEngine) PubToTopic(topic string, signingkey *ecdsa.PrivateKey, mod
447458 }
448459
449460 me .TopicData [topic ] = tdata
461+ topicDataLen := len (me .TopicData )
462+ me .DataMu .Unlock ()
450463
451464 log .Printf ("MQTT Engine %s: added pub topic %s. Engine now has %d topics" , me .Creator , topic , len (me .TopicData ))
452465
@@ -460,34 +473,35 @@ func (me *MqttEngine) PubToTopic(topic string, signingkey *ecdsa.PrivateKey, mod
460473 },
461474 },
462475 }); err != nil {
463- return me . TopicData , fmt .Errorf ("AddTopic: failed to subscribe to topic %s: %v" , topic , err )
476+ return fmt .Errorf ("AddTopic: failed to subscribe to topic %s: %v" , topic , err )
464477 }
465- log .Printf ("MQTT Engine %s: added topic %s to running MQTT Engine. Engine now has %d topics" , me .Creator , topic , len ( me . TopicData ) )
478+ log .Printf ("MQTT Engine %s: added topic %s to running MQTT Engine. Engine now has %d topics" , me .Creator , topic , topicDataLen )
466479 }
467480
468- return me . TopicData , nil
481+ return nil
469482}
470483
471484func (me * MqttEngine ) SubToTopic (topic string ,
472485 subscriberCh chan MqttPkgIn , mode string , validate bool ,
473- ) ( map [ string ] TopicData , error ) {
486+ ) error {
474487 log .Printf ("MQTT Engine: SubToTopic: topic %s, subscriberCh %v, mode %s, validate %t" , topic , subscriberCh , mode , validate )
475488 if topic == "" {
476- return me . TopicData , fmt .Errorf ("SubToTopic: topic not specified" )
489+ return fmt .Errorf ("SubToTopic: topic not specified" )
477490 }
478491
479492 if mode != "raw" && mode != "struct" {
480- return me . TopicData , fmt .Errorf ("SubToTopic: unknown mode: %s" , mode )
493+ return fmt .Errorf ("SubToTopic: unknown mode: %s" , mode )
481494 }
482495
483496 if subscriberCh == nil {
484- return me . TopicData , fmt .Errorf ("SubToTopic: subscriber channel not specified" )
497+ return fmt .Errorf ("SubToTopic: subscriber channel not specified" )
485498 }
486499
487500 if strings .HasSuffix (topic , "/#" ) {
488501 me .PrefixTopics [strings .TrimSuffix (topic , "#" )] = true
489502 }
490503
504+ me .DataMu .Lock ()
491505 if _ , exist := me .TopicData [topic ]; ! exist {
492506 me .TopicData [topic ] = TopicData {
493507 Topic : topic ,
@@ -500,7 +514,9 @@ func (me *MqttEngine) SubToTopic(topic string,
500514 tdata .SubscriberCh = subscriberCh
501515
502516 me .TopicData [topic ] = tdata
503- log .Printf ("MQTT Engine %s: added sub topic %s (validate %t, mode %s). Engine now has %d topics" , me .Creator , topic , validate , mode , len (me .TopicData ))
517+ topicDataLen := len (me .TopicData )
518+ me .DataMu .Unlock ()
519+ log .Printf ("MQTT Engine %s: added sub topic %s (validate %t, mode %s). Engine now has %d topics" , me .Creator , topic , validate , mode , topicDataLen )
504520
505521 // does the MqttEngine already have a connection manager (i.e. is it already running)
506522 if me .ConnectionManager != nil {
@@ -512,7 +528,7 @@ func (me *MqttEngine) SubToTopic(topic string,
512528 },
513529 },
514530 }); err != nil {
515- return me . TopicData , fmt .Errorf ("SubToTopic: failed to subscribe to topic %s: %v" , topic , err )
531+ return fmt .Errorf ("SubToTopic: failed to subscribe to topic %s: %v" , topic , err )
516532 }
517533 var topics , prefixTopics []string
518534 for t := range me .TopicData {
@@ -522,25 +538,29 @@ func (me *MqttEngine) SubToTopic(topic string,
522538 prefixTopics = append (prefixTopics , t )
523539 }
524540 log .Printf ("MQTT Engine %s: added sub topic %s to running MQTT Engine." , me .Creator , topic )
525- log .Printf ("Engine now has %d topics: %v and %d prefix topics: %v" , len ( me . TopicData ) , topics , len (me .PrefixTopics ), prefixTopics )
541+ log .Printf ("Engine now has %d topics: %v and %d prefix topics: %v" , topicDataLen , topics , len (me .PrefixTopics ), prefixTopics )
526542 }
527543
544+ me .DataMu .Lock ()
528545 log .Printf ("MQTT Engine %s: TopicData for topic %s: %+v" , me .Creator , topic , me .TopicData [topic ])
546+ me .DataMu .Unlock ()
529547
530- return me . TopicData , nil
548+ return nil
531549}
532550
533- func (me * MqttEngine ) RemoveTopic (topic string ) ( map [ string ] TopicData , error ) {
551+ func (me * MqttEngine ) RemoveTopic (topic string ) error {
534552 if me .ConnectionManager != nil {
535553 if _ , err := me .ConnectionManager .Unsubscribe (context .Background (), & paho.Unsubscribe {
536554 Topics : []string {topic },
537555 }); err != nil {
538- return me . TopicData , fmt .Errorf ("RemoveTopic: failed to unsubscribe from topic %s: %v" , topic , err )
556+ return fmt .Errorf ("RemoveTopic: failed to unsubscribe from topic %s: %v" , topic , err )
539557 }
540558 }
559+ me .DataMu .Lock ()
541560 delete (me .TopicData , topic )
542561 log .Printf ("MQTT Engine: removed topic %s. Engine now has %d topics" , topic , len (me .TopicData ))
543- return me .TopicData , nil
562+ me .DataMu .Unlock ()
563+ return nil
544564}
545565
546566func (me * MqttEngine ) StartEngine () (chan MqttEngineCmd , chan MqttPkgOut , chan MqttPkgIn , error ) {
@@ -601,14 +621,20 @@ func (me *MqttEngine) SetupInterruptHandler() {
601621}
602622
603623func (me * MqttEngine ) FetchTopicData (topic string ) (TopicData , error ) {
604- if td , exist := me .TopicData [topic ]; exist {
605- log .Printf ("MQTT Engine %s: topic %s: exact match found. TopicData: %+v" , me .Creator , topic , td )
624+ me .DataMu .Lock ()
625+ td , exist := me .TopicData [topic ]
626+ me .DataMu .Unlock ()
627+ if exist {
628+ log .Printf ("MQTT Engine %s: topic %s: exact match found." , me .Creator , topic )
606629 return td , nil
607630 }
608631 for prefix := range me .PrefixTopics {
609632 if strings .HasPrefix (topic , prefix ) {
633+ me .DataMu .Lock ()
634+ tdPrefix := me .TopicData [topic ]
610635 log .Printf ("MQTT Engine %s: topic %s matches prefix %s. TopicData: %+v" , me .Creator , topic , prefix , me .TopicData [prefix ])
611- return me .TopicData [prefix + "#" ], nil
636+ me .DataMu .Unlock ()
637+ return tdPrefix , nil
612638 }
613639 }
614640 return TopicData {}, fmt .Errorf ("FetchTopicData: topic %s not found" , topic )
0 commit comments