Negotiate Lower Bandwidth / Higher Density Packets for Peers #428
|
@ -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)
|
||||
sarah marked this conversation as resolved
Outdated
|
||||
} else {
|
||||
packet = *parsePacket
|
||||
}
|
||||
|
||||
sarah marked this conversation as resolved
Outdated
dan
commented
I'm a little nervous mixing unspecified Ids, event IDs are strings, even tho they should be populated by int -> strings only? its not type specified anywhere so someone could make it binary or strings and either could generate a '|', contexts are strings that right now use '.' as seperators... could we use Pascal style strings here? neither id nor context should exceed 256 bytes so just have each lead with a byte of length to parse? I'm a little nervous mixing unspecified Ids, event IDs are strings, even tho they should be populated by int -> strings only? its not type specified anywhere so someone could make it binary or strings and either could generate a '|', contexts are strings that right now use '.' as seperators...
we have a lot of string manipulation based on not well documented seperators and we're mixing it with binary data.
could we use Pascal style strings here? neither id nor context should exceed 256 bytes so just have each lead with a byte of length to parse?
|
||||
} 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
this is a big chunk, might be best moved to a function?