mirror of
https://github.com/fhmq/hmq.git
synced 2026-05-03 06:38:33 +00:00
packet
This commit is contained in:
210
lib/message/unsubscribe.go
Executable file
210
lib/message/unsubscribe.go
Executable file
@@ -0,0 +1,210 @@
|
||||
// Copyright (c) 2014 The SurgeMQ Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package message
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// An UNSUBSCRIBE Packet is sent by the Client to the Server, to unsubscribe from topics.
|
||||
type UnsubscribeMessage struct {
|
||||
header
|
||||
|
||||
topics [][]byte
|
||||
}
|
||||
|
||||
var _ Message = (*UnsubscribeMessage)(nil)
|
||||
|
||||
// NewUnsubscribeMessage creates a new UNSUBSCRIBE message.
|
||||
func NewUnsubscribeMessage() *UnsubscribeMessage {
|
||||
msg := &UnsubscribeMessage{}
|
||||
msg.SetType(UNSUBSCRIBE)
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
func (this UnsubscribeMessage) String() string {
|
||||
msgstr := fmt.Sprintf("%s", this.header)
|
||||
|
||||
for i, t := range this.topics {
|
||||
msgstr = fmt.Sprintf("%s, Topic%d=%s", msgstr, i, string(t))
|
||||
}
|
||||
|
||||
return msgstr
|
||||
}
|
||||
|
||||
// Topics returns a list of topics sent by the Client.
|
||||
func (this *UnsubscribeMessage) Topics() [][]byte {
|
||||
return this.topics
|
||||
}
|
||||
|
||||
// AddTopic adds a single topic to the message.
|
||||
func (this *UnsubscribeMessage) AddTopic(topic []byte) {
|
||||
if this.TopicExists(topic) {
|
||||
return
|
||||
}
|
||||
|
||||
this.topics = append(this.topics, topic)
|
||||
this.dirty = true
|
||||
}
|
||||
|
||||
// RemoveTopic removes a single topic from the list of existing ones in the message.
|
||||
// If topic does not exist it just does nothing.
|
||||
func (this *UnsubscribeMessage) RemoveTopic(topic []byte) {
|
||||
var i int
|
||||
var t []byte
|
||||
var found bool
|
||||
|
||||
for i, t = range this.topics {
|
||||
if bytes.Equal(t, topic) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
this.topics = append(this.topics[:i], this.topics[i+1:]...)
|
||||
}
|
||||
|
||||
this.dirty = true
|
||||
}
|
||||
|
||||
// TopicExists checks to see if a topic exists in the list.
|
||||
func (this *UnsubscribeMessage) TopicExists(topic []byte) bool {
|
||||
for _, t := range this.topics {
|
||||
if bytes.Equal(t, topic) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *UnsubscribeMessage) Len() int {
|
||||
if !this.dirty {
|
||||
return len(this.dbuf)
|
||||
}
|
||||
|
||||
ml := this.msglen()
|
||||
|
||||
if err := this.SetRemainingLength(int32(ml)); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return this.header.msglen() + ml
|
||||
}
|
||||
|
||||
// Decode reads from the io.Reader parameter until a full message is decoded, or
|
||||
// when io.Reader returns EOF or error. The first return value is the number of
|
||||
// bytes read from io.Reader. The second is error if Decode encounters any problems.
|
||||
func (this *UnsubscribeMessage) Decode(src []byte) (int, error) {
|
||||
total := 0
|
||||
|
||||
hn, err := this.header.decode(src[total:])
|
||||
total += hn
|
||||
if err != nil {
|
||||
return total, err
|
||||
}
|
||||
|
||||
//this.packetId = binary.BigEndian.Uint16(src[total:])
|
||||
this.packetId = src[total : total+2]
|
||||
total += 2
|
||||
|
||||
remlen := int(this.remlen) - (total - hn)
|
||||
for remlen > 0 {
|
||||
t, n, err := readLPBytes(src[total:])
|
||||
total += n
|
||||
if err != nil {
|
||||
return total, err
|
||||
}
|
||||
|
||||
this.topics = append(this.topics, t)
|
||||
remlen = remlen - n - 1
|
||||
}
|
||||
|
||||
if len(this.topics) == 0 {
|
||||
return 0, fmt.Errorf("unsubscribe/Decode: Empty topic list")
|
||||
}
|
||||
|
||||
this.dirty = false
|
||||
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// Encode returns an io.Reader in which the encoded bytes can be read. The second
|
||||
// return value is the number of bytes encoded, so the caller knows how many bytes
|
||||
// there will be. If Encode returns an error, then the first two return values
|
||||
// should be considered invalid.
|
||||
// Any changes to the message after Encode() is called will invalidate the io.Reader.
|
||||
func (this *UnsubscribeMessage) Encode(dst []byte) (int, error) {
|
||||
if !this.dirty {
|
||||
if len(dst) < len(this.dbuf) {
|
||||
return 0, fmt.Errorf("unsubscribe/Encode: Insufficient buffer size. Expecting %d, got %d.", len(this.dbuf), len(dst))
|
||||
}
|
||||
|
||||
return copy(dst, this.dbuf), nil
|
||||
}
|
||||
|
||||
hl := this.header.msglen()
|
||||
ml := this.msglen()
|
||||
|
||||
if len(dst) < hl+ml {
|
||||
return 0, fmt.Errorf("unsubscribe/Encode: Insufficient buffer size. Expecting %d, got %d.", hl+ml, len(dst))
|
||||
}
|
||||
|
||||
if err := this.SetRemainingLength(int32(ml)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
total := 0
|
||||
|
||||
n, err := this.header.encode(dst[total:])
|
||||
total += n
|
||||
if err != nil {
|
||||
return total, err
|
||||
}
|
||||
|
||||
if this.PacketId() == 0 {
|
||||
this.SetPacketId(uint16(atomic.AddUint64(&gPacketId, 1) & 0xffff))
|
||||
//this.packetId = uint16(atomic.AddUint64(&gPacketId, 1) & 0xffff)
|
||||
}
|
||||
|
||||
n = copy(dst[total:], this.packetId)
|
||||
//binary.BigEndian.PutUint16(dst[total:], this.packetId)
|
||||
total += n
|
||||
|
||||
for _, t := range this.topics {
|
||||
n, err := writeLPBytes(dst[total:], t)
|
||||
total += n
|
||||
if err != nil {
|
||||
return total, err
|
||||
}
|
||||
}
|
||||
|
||||
return total, nil
|
||||
}
|
||||
|
||||
func (this *UnsubscribeMessage) msglen() int {
|
||||
// packet ID
|
||||
total := 2
|
||||
|
||||
for _, t := range this.topics {
|
||||
total += 2 + len(t)
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
Reference in New Issue
Block a user