cwtch/protocol/model/peermessage.go

54 lines
1.6 KiB
Go

package model
import (
"bytes"
"errors"
)
// PeerMessage is an encapsulation that can be used by higher level applications
type PeerMessage struct {
// ID **must** only contain alphanumeric characters separated by period.
ID string // A unique Message ID (primarily used for acknowledgments)
// Context **must** only contain alphanumeric characters separated by period.
Context string // A unique context identifier i.e. im.cwtch.chat
// Data can contain anything
Data []byte // A data packet.
}
// Serialize constructs an efficient serialized representation
// Format: [ID String] | [Context String] | Binary Data
func (m *PeerMessage) Serialize() []byte {
return append(append([]byte(m.ID+"|"), []byte(m.Context+"|")...), m.Data...)
}
// ParsePeerMessage returns either a deserialized PeerMessage or an error if it is malformed
func ParsePeerMessage(message []byte) (*PeerMessage, error) {
// find the identifier prefix
idTerminator := bytes.IndexByte(message, '|')
if idTerminator != -1 && idTerminator+1 < len(message) {
// find the context terminator prefix
contextbegin := idTerminator + 1
contextTerminator := bytes.IndexByte(message[contextbegin:], '|')
if contextTerminator != -1 {
// check that we have data
dataBegin := contextbegin + contextTerminator + 1
var data []byte
if dataBegin < len(message) {
data = message[dataBegin:]
}
// compile the message
return &PeerMessage{
ID: string(message[0:idTerminator]),
Context: string(message[contextbegin : contextbegin+contextTerminator]),
Data: data,
}, nil
}
}
return nil, errors.New("invalid message")
}