// TODO: wanna implement trie. but regexp works well. // retain should persist their data. though, how do we fetch it efficiently... func (self *Momonga) RetainMatch(topic string) []*codec.PublishMessage { var result []*codec.PublishMessage orig := topic // TODO: should validate illegal wildcards like /debug/#/hello topic = strings.Replace(topic, "+", "[^/]+", -1) topic = strings.Replace(topic, "#", ".*", -1) reg, err := regexp.Compile(topic) if err != nil { fmt.Printf("Regexp Error: %s", err) } all := false if string(orig[0:1]) == "#" || string(orig[0:1]) == "+" { all = true } // TODO:これどうにかしたいなー・・・。とは思いつつDBからめて素敵にやるってなるとあんまりいいアイデアない itr := self.DataStore.Iterator() for ; itr.Valid(); itr.Next() { k := string(itr.Key()) if all && (len(k) > 0 && k[0:1] == "$") { // [MQTT-4.7.2-1] The Server MUST NOT match Topic Filters starting with a wildcard character (# or +) // with Topic Names beginning with a $ character // NOTE: Qlobber doesn't support this feature yet continue } if reg.MatchString(k) { data := itr.Value() p, _ := codec.ParseMessage(bytes.NewReader(data), 0) if v, ok := p.(*codec.PublishMessage); ok { result = append(result, v) } } } return result }
func (self *MyConnection) ParseMessage() (codec.Message, error) { // self.Mutex.RLock() // defer self.Mutex.RUnlock() if self.Keepalive > 0 { if cn, ok := self.MyConnection.(net.Conn); ok { cn.SetReadDeadline(self.Last.Add(time.Duration(int(float64(self.Keepalive)*1.5)) * time.Second)) } } if self.Reader == nil { panic("reader is null") } message, err := codec.ParseMessage(self.Reader, self.MaxMessageSize) if err != nil { self.logger.Debug(">>> Message: %s\n", err) if v, ok := self.Events["error"].(func(error)); ok { v(err) } return nil, err } self.logger.Debug("Read Message: [%s] %+v", message.GetTypeAsString(), message) if v, ok := self.Events["parsed"]; ok { if cb, ok := v.(func()); ok { cb() } } // 以下callbackを呼ぶだけのコード switch message.GetType() { case codec.PACKET_TYPE_PUBLISH: p := message.(*codec.PublishMessage) if v, ok := self.Events["publish"]; ok { if cb, ok := v.(func(*codec.PublishMessage)); ok { cb(p) } } break case codec.PACKET_TYPE_CONNACK: p := message.(*codec.ConnackMessage) if v, ok := self.Events["connack"]; ok { if cb, ok := v.(func(uint8)); ok { cb(p.ReturnCode) } } break case codec.PACKET_TYPE_PUBACK: p := message.(*codec.PubackMessage) if v, ok := self.Events["puback"]; ok { if cb, ok := v.(func(uint16)); ok { cb(p.PacketIdentifier) } } break case codec.PACKET_TYPE_PUBREC: p := message.(*codec.PubrecMessage) if v, ok := self.Events["pubrec"]; ok { if cb, ok := v.(func(uint16)); ok { cb(p.PacketIdentifier) } } break case codec.PACKET_TYPE_PUBREL: // PUBRELを受けるということはReceiverとして受けるということ p := message.(*codec.PubrelMessage) if v, ok := self.Events["pubrel"]; ok { if cb, ok := v.(func(uint16)); ok { cb(p.PacketIdentifier) } } break case codec.PACKET_TYPE_PUBCOMP: // PUBCOMPを受けるということはSenderとして受けるということ。 p := message.(*codec.PubcompMessage) if v, ok := self.Events["pubcomp"]; ok { if cb, ok := v.(func(uint16)); ok { cb(p.PacketIdentifier) } } break case codec.PACKET_TYPE_PINGREQ: if v, ok := self.Events["pingreq"]; ok { if cb, ok := v.(func()); ok { cb() } } break case codec.PACKET_TYPE_PINGRESP: if v, ok := self.Events["pingresp"]; ok { if cb, ok := v.(func()); ok { cb() } } break case codec.PACKET_TYPE_SUBACK: p := message.(*codec.SubackMessage) if v, ok := self.Events["suback"]; ok { if cb, ok := v.(func(uint16, int)); ok { cb(p.PacketIdentifier, 0) } } break case codec.PACKET_TYPE_UNSUBACK: p := message.(*codec.UnsubackMessage) if v, ok := self.Events["unsuback"]; ok { if cb, ok := v.(func(uint16)); ok { cb(p.PacketIdentifier) } } break case codec.PACKET_TYPE_CONNECT: p := message.(*codec.ConnectMessage) if v, ok := self.Events["connect"]; ok { if cb, ok := v.(func(*codec.ConnectMessage)); ok { cb(p) } } break case codec.PACKET_TYPE_SUBSCRIBE: p := message.(*codec.SubscribeMessage) if v, ok := self.Events["subscribe"]; ok { if cb, ok := v.(func(*codec.SubscribeMessage)); ok { cb(p) } } break case codec.PACKET_TYPE_DISCONNECT: if v, ok := self.Events["disconnect"]; ok { if cb, ok := v.(func()); ok { cb() } } break case codec.PACKET_TYPE_UNSUBSCRIBE: p := message.(*codec.UnsubscribeMessage) if v, ok := self.Events["unsubscribe"]; ok { if cb, ok := v.(func(uint16, int, []codec.SubscribePayload)); ok { cb(p.PacketIdentifier, 0, p.Payload) } } break default: self.logger.Error("Unhandled message: %+v\n", message) } self.invalidateTimer() self.Last = time.Now() return message, err }