Factor out serialization/parsing code into protocol.Model
This commit is contained in:
parent
6bb510e39e
commit
ff4249e2bc
|
@ -1,11 +1,9 @@
|
|||
package connections
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cwtch.im/cwtch/event"
|
||||
model2 "cwtch.im/cwtch/protocol/model"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"git.openprivacy.ca/cwtch.im/tapir"
|
||||
"git.openprivacy.ca/cwtch.im/tapir/applications"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
|
@ -103,39 +101,14 @@ func (pa *PeerApp) listen() {
|
|||
if pa.version.Load() == 0x01 {
|
||||
err = json.Unmarshal(message, &packet)
|
||||
} else if pa.version.Load() == 0x02 {
|
||||
|
||||
// assume the encoding is invalid
|
||||
err = errors.New("invalid message")
|
||||
|
||||
// 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 {
|
||||
err = nil
|
||||
|
||||
// check that we have data
|
||||
dataBegin := contextbegin + contextTerminator + 1
|
||||
var data []byte
|
||||
if dataBegin < len(message) {
|
||||
data = message[dataBegin:]
|
||||
}
|
||||
|
||||
// compile the message
|
||||
packet = model2.PeerMessage{
|
||||
ID: string(message[0:idTerminator]),
|
||||
Context: string(message[contextbegin : contextbegin+contextTerminator]),
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parsePacket, parseErr := model2.ParsePeerMessage(message)
|
||||
// if all else fails...attempt to process this message as a version 1 message
|
||||
if err != nil {
|
||||
if parseErr != nil {
|
||||
err = json.Unmarshal(message, &packet)
|
||||
} else {
|
||||
packet = *parsePacket
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Errorf("invalid version")
|
||||
pa.OnClose(pa.connection.Hostname())
|
||||
|
@ -170,7 +143,7 @@ func (pa *PeerApp) SendMessage(message model2.PeerMessage) error {
|
|||
|
||||
if pa.version.Load() == 0x02 {
|
||||
// treat data as a pre-serialized string, not as a byte array (which will be base64 encoded and bloat the packet size)
|
||||
serialized = append(append([]byte(message.ID+"|"), []byte(message.Context+"|")...), message.Data...)
|
||||
serialized = message.Serialize()
|
||||
} else {
|
||||
serialized, err = json.Marshal(message)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,52 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// PeerMessage is an encapsulation that can be used by higher level applications
|
||||
type PeerMessage struct {
|
||||
ID string // A unique Message ID (primarily used for acknowledgments)
|
||||
// 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 []byte // A data packet.
|
||||
|
||||
// Data can contain anything
|
||||
Data []byte // A data packet.
|
||||
}
|
||||
|
||||
// Serialize constructs an efficient serialized representation
|
||||
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")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue