lib/protocol: Use DeviceID in protocol messages, with custom marshalling

This makes the device ID a real type that can be used in the protobuf
schema. That avoids the juggling back and forth from []byte in a bunch
of places and simplifies the code.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3695
This commit is contained in:
Jakob Borg 2016-10-29 21:56:24 +00:00 committed by Audrius Butkevicius
parent 1cdfef4d6a
commit 0296c23685
13 changed files with 728 additions and 195 deletions

View File

@ -7,7 +7,6 @@
package main package main
import ( import (
"bytes"
"crypto/rand" "crypto/rand"
"encoding/binary" "encoding/binary"
"flag" "flag"
@ -45,7 +44,7 @@ func main() {
flag.Parse() flag.Parse()
if fake { if fake {
log.Println("My ID:", protocol.DeviceIDFromBytes(myID)) log.Println("My ID:", myID)
} }
runbeacon(beacon.NewMulticast(mc), fake) runbeacon(beacon.NewMulticast(mc), fake)
@ -75,17 +74,17 @@ func recv(bc beacon.Interface) {
var ann discover.Announce var ann discover.Announce
ann.Unmarshal(data[4:]) ann.Unmarshal(data[4:])
if bytes.Equal(ann.ID, myID) { if ann.ID == myID {
// This is one of our own fake packets, don't print it. // This is one of our own fake packets, don't print it.
continue continue
} }
// Print announcement details for the first packet from a given // Print announcement details for the first packet from a given
// device ID and source address, or if -all was given. // device ID and source address, or if -all was given.
key := string(ann.ID) + src.String() key := ann.ID.String() + src.String()
if all || !seen[key] { if all || !seen[key] {
log.Printf("Announcement from %v\n", src) log.Printf("Announcement from %v\n", src)
log.Printf(" %v at %s\n", protocol.DeviceIDFromBytes(ann.ID), strings.Join(ann.Addresses, ", ")) log.Printf(" %v at %s\n", ann.ID, strings.Join(ann.Addresses, ", "))
seen[key] = true seen[key] = true
} }
} }
@ -106,9 +105,9 @@ func send(bc beacon.Interface) {
} }
// returns a random but recognizable device ID // returns a random but recognizable device ID
func randomDeviceID() []byte { func randomDeviceID() protocol.DeviceID {
var id [32]byte var id protocol.DeviceID
copy(id[:], randomPrefix) copy(id[:], randomPrefix)
rand.Read(id[len(randomPrefix):]) rand.Read(id[len(randomPrefix):])
return id[:] return id
} }

View File

@ -10,7 +10,6 @@
package discover package discover
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"io" "io"
@ -115,7 +114,7 @@ func (c *localClient) Error() error {
func (c *localClient) announcementPkt() Announce { func (c *localClient) announcementPkt() Announce {
return Announce{ return Announce{
ID: c.myID[:], ID: c.myID,
Addresses: c.addrList.AllAddresses(), Addresses: c.addrList.AllAddresses(),
InstanceID: rand.Int63(), InstanceID: rand.Int63(),
} }
@ -173,10 +172,10 @@ func (c *localClient) recvAnnouncements(b beacon.Interface) {
continue continue
} }
l.Debugf("discover: Received local announcement from %s for %s", addr, protocol.DeviceIDFromBytes(pkt.ID)) l.Debugf("discover: Received local announcement from %s for %s", addr, pkt.ID)
var newDevice bool var newDevice bool
if !bytes.Equal(pkt.ID, c.myID[:]) { if pkt.ID != c.myID {
newDevice = c.registerDevice(addr, pkt) newDevice = c.registerDevice(addr, pkt)
} }
@ -192,20 +191,17 @@ func (c *localClient) recvAnnouncements(b beacon.Interface) {
} }
func (c *localClient) registerDevice(src net.Addr, device Announce) bool { func (c *localClient) registerDevice(src net.Addr, device Announce) bool {
var id protocol.DeviceID
copy(id[:], device.ID)
// Remember whether we already had a valid cache entry for this device. // Remember whether we already had a valid cache entry for this device.
// If the instance ID has changed the remote device has restarted since // If the instance ID has changed the remote device has restarted since
// we last heard from it, so we should treat it as a new device. // we last heard from it, so we should treat it as a new device.
ce, existsAlready := c.Get(id) ce, existsAlready := c.Get(device.ID)
isNewDevice := !existsAlready || time.Since(ce.when) > CacheLifeTime || ce.instanceID != device.InstanceID isNewDevice := !existsAlready || time.Since(ce.when) > CacheLifeTime || ce.instanceID != device.InstanceID
// Any empty or unspecified addresses should be set to the source address // Any empty or unspecified addresses should be set to the source address
// of the announcement. We also skip any addresses we can't parse. // of the announcement. We also skip any addresses we can't parse.
l.Debugln("discover: Registering addresses for", id) l.Debugln("discover: Registering addresses for", device.ID)
var validAddresses []string var validAddresses []string
for _, addr := range device.Addresses { for _, addr := range device.Addresses {
u, err := url.Parse(addr) u, err := url.Parse(addr)
@ -248,7 +244,7 @@ func (c *localClient) registerDevice(src net.Addr, device Announce) bool {
} }
} }
c.Set(id, CacheEntry{ c.Set(device.ID, CacheEntry{
Addresses: validAddresses, Addresses: validAddresses,
when: time.Now(), when: time.Now(),
found: true, found: true,
@ -257,7 +253,7 @@ func (c *localClient) registerDevice(src net.Addr, device Announce) bool {
if isNewDevice { if isNewDevice {
events.Default.Log(events.DeviceDiscovered, map[string]interface{}{ events.Default.Log(events.DeviceDiscovered, map[string]interface{}{
"device": id.String(), "device": device.ID.String(),
"addrs": validAddresses, "addrs": validAddresses,
}) })
} }

View File

@ -18,6 +18,8 @@ import fmt "fmt"
import math "math" import math "math"
import _ "github.com/gogo/protobuf/gogoproto" import _ "github.com/gogo/protobuf/gogoproto"
import github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
import io "io" import io "io"
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -30,9 +32,9 @@ var _ = math.Inf
const _ = proto.GoGoProtoPackageIsVersion1 const _ = proto.GoGoProtoPackageIsVersion1
type Announce struct { type Announce struct {
ID []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` ID github_com_syncthing_syncthing_lib_protocol.DeviceID `protobuf:"bytes,1,opt,name=id,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.DeviceID" json:"id"`
Addresses []string `protobuf:"bytes,2,rep,name=addresses" json:"addresses,omitempty"` Addresses []string `protobuf:"bytes,2,rep,name=addresses" json:"addresses,omitempty"`
InstanceID int64 `protobuf:"varint,3,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` InstanceID int64 `protobuf:"varint,3,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"`
} }
func (m *Announce) Reset() { *m = Announce{} } func (m *Announce) Reset() { *m = Announce{} }
@ -58,12 +60,14 @@ func (m *Announce) MarshalTo(data []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.ID) > 0 { data[i] = 0xa
data[i] = 0xa i++
i++ i = encodeVarintLocal(data, i, uint64(m.ID.ProtoSize()))
i = encodeVarintLocal(data, i, uint64(len(m.ID))) n1, err := m.ID.MarshalTo(data[i:])
i += copy(data[i:], m.ID) if err != nil {
return 0, err
} }
i += n1
if len(m.Addresses) > 0 { if len(m.Addresses) > 0 {
for _, s := range m.Addresses { for _, s := range m.Addresses {
data[i] = 0x12 data[i] = 0x12
@ -117,10 +121,8 @@ func encodeVarintLocal(data []byte, offset int, v uint64) int {
func (m *Announce) ProtoSize() (n int) { func (m *Announce) ProtoSize() (n int) {
var l int var l int
_ = l _ = l
l = len(m.ID) l = m.ID.ProtoSize()
if l > 0 { n += 1 + l + sovLocal(uint64(l))
n += 1 + l + sovLocal(uint64(l))
}
if len(m.Addresses) > 0 { if len(m.Addresses) > 0 {
for _, s := range m.Addresses { for _, s := range m.Addresses {
l = len(s) l = len(s)
@ -201,9 +203,8 @@ func (m *Announce) Unmarshal(data []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.ID = append(m.ID[:0], data[iNdEx:postIndex]...) if err := m.ID.Unmarshal(data[iNdEx:postIndex]); err != nil {
if m.ID == nil { return err
m.ID = []byte{}
} }
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
@ -381,18 +382,20 @@ var (
) )
var fileDescriptorLocal = []byte{ var fileDescriptorLocal = []byte{
// 194 bytes of a gzipped FileDescriptorProto // 235 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xce, 0xc9, 0x4f, 0x4e, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xce, 0xc9, 0x4f, 0x4e,
0xcc, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x48, 0xc9, 0x2c, 0x4e, 0xce, 0x2f, 0x4b, 0xcc, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x48, 0xc9, 0x2c, 0x4e, 0xce, 0x2f, 0x4b,
0x2d, 0x92, 0xd2, 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0x2d, 0x92, 0xd2, 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf,
0x4f, 0xcf, 0xd7, 0x07, 0x2b, 0x48, 0x2a, 0x4d, 0x03, 0xf3, 0xc0, 0x1c, 0x30, 0x0b, 0xa2, 0x51, 0x4f, 0xcf, 0xd7, 0x07, 0x2b, 0x48, 0x2a, 0x4d, 0x03, 0xf3, 0xc0, 0x1c, 0x30, 0x0b, 0xa2, 0x51,
0xa9, 0x90, 0x8b, 0xc3, 0x31, 0x2f, 0x2f, 0xbf, 0x34, 0x2f, 0x39, 0x55, 0x48, 0x8c, 0x8b, 0x29, 0x69, 0x2d, 0x23, 0x17, 0x87, 0x63, 0x5e, 0x5e, 0x7e, 0x69, 0x5e, 0x72, 0xaa, 0x50, 0x10, 0x17,
0x33, 0x45, 0x82, 0x51, 0x81, 0x51, 0x83, 0xc7, 0x89, 0xed, 0xd1, 0x3d, 0x79, 0x26, 0x4f, 0x97, 0x53, 0x66, 0x8a, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x8f, 0x93, 0xd3, 0x89, 0x7b, 0xf2, 0x0c, 0xb7,
0x20, 0xa0, 0x88, 0x90, 0x0c, 0x17, 0x67, 0x62, 0x4a, 0x4a, 0x51, 0x6a, 0x71, 0x71, 0x6a, 0xb1, 0xee, 0xc9, 0x9b, 0x20, 0x99, 0x57, 0x5c, 0x99, 0x97, 0x5c, 0x92, 0x91, 0x99, 0x97, 0x8e, 0xc4,
0x04, 0x93, 0x02, 0xb3, 0x06, 0x67, 0x10, 0x42, 0x40, 0x48, 0x9f, 0x8b, 0x3b, 0x33, 0xaf, 0xb8, 0xca, 0xc9, 0x4c, 0x82, 0x58, 0x91, 0x9c, 0x9f, 0xa3, 0xe7, 0x92, 0x5a, 0x96, 0x99, 0x9c, 0xea,
0x24, 0x11, 0x68, 0x42, 0x3c, 0x50, 0x3b, 0x33, 0x50, 0x3b, 0xb3, 0x13, 0x1f, 0x50, 0x3b, 0x97, 0xe9, 0xf2, 0xe8, 0x9e, 0x3c, 0x93, 0xa7, 0x4b, 0x10, 0xd0, 0x34, 0x21, 0x19, 0x2e, 0xce, 0xc4,
0x27, 0x54, 0x18, 0x68, 0x0c, 0x17, 0x4c, 0x89, 0x67, 0x8a, 0x93, 0xc8, 0x89, 0x87, 0x72, 0x0c, 0x94, 0x94, 0xa2, 0xd4, 0xe2, 0xe2, 0xd4, 0x62, 0x09, 0x26, 0x05, 0x66, 0x0d, 0xce, 0x20, 0x84,
0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x00, 0xe2, 0x07, 0x8f, 0xe4, 0x18, 0x16, 0x3c, 0x96, 0x63, 0x4c, 0x80, 0x90, 0x3e, 0x17, 0x77, 0x66, 0x5e, 0x71, 0x49, 0x22, 0xd0, 0xf6, 0x78, 0xa0, 0xd5, 0xcc,
0x62, 0x03, 0xbb, 0xc7, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x91, 0x3f, 0x96, 0x25, 0xd7, 0x00, 0x40, 0xab, 0x99, 0x9d, 0xf8, 0x80, 0xda, 0xb9, 0x3c, 0xa1, 0xc2, 0x40, 0x63, 0xb8, 0x60, 0x4a,
0x00, 0x00, 0x3c, 0x53, 0x9c, 0x44, 0x4e, 0x3c, 0x94, 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0x02, 0x10, 0x3f,
0x78, 0x24, 0xc7, 0xb0, 0xe0, 0xb1, 0x1c, 0x63, 0x12, 0x1b, 0xd8, 0x05, 0xc6, 0x80, 0x00, 0x00,
0x00, 0xff, 0xff, 0xa4, 0x46, 0x4f, 0x13, 0x14, 0x01, 0x00, 0x00,
} }

View File

@ -9,7 +9,7 @@ option (gogoproto.sizer_all) = false;
option (gogoproto.protosizer_all) = true; option (gogoproto.protosizer_all) = true;
message Announce { message Announce {
bytes id = 1 [(gogoproto.customname) = "ID"]; bytes id = 1 [(gogoproto.customname) = "ID", (gogoproto.customtype) = "github.com/syncthing/syncthing/lib/protocol.DeviceID", (gogoproto.nullable) = false];
repeated string addresses = 2; repeated string addresses = 2;
int64 instance_id = 3 [(gogoproto.customname) = "InstanceID"]; int64 instance_id = 3 [(gogoproto.customname) = "InstanceID"];
} }

View File

@ -40,7 +40,7 @@ func TestLocalInstanceIDShouldTriggerNew(t *testing.T) {
src := &net.UDPAddr{IP: []byte{10, 20, 30, 40}, Port: 50} src := &net.UDPAddr{IP: []byte{10, 20, 30, 40}, Port: 50}
new := lc.registerDevice(src, Announce{ new := lc.registerDevice(src, Announce{
ID: []byte{10, 20, 30, 40, 50, 60, 70, 80, 90}, ID: protocol.DeviceID{10, 20, 30, 40, 50, 60, 70, 80, 90},
Addresses: []string{"tcp://0.0.0.0:22000"}, Addresses: []string{"tcp://0.0.0.0:22000"},
InstanceID: 1234567890, InstanceID: 1234567890,
}) })
@ -50,7 +50,7 @@ func TestLocalInstanceIDShouldTriggerNew(t *testing.T) {
} }
new = lc.registerDevice(src, Announce{ new = lc.registerDevice(src, Announce{
ID: []byte{10, 20, 30, 40, 50, 60, 70, 80, 90}, ID: protocol.DeviceID{10, 20, 30, 40, 50, 60, 70, 80, 90},
Addresses: []string{"tcp://0.0.0.0:22000"}, Addresses: []string{"tcp://0.0.0.0:22000"},
InstanceID: 1234567890, InstanceID: 1234567890,
}) })
@ -60,7 +60,7 @@ func TestLocalInstanceIDShouldTriggerNew(t *testing.T) {
} }
new = lc.registerDevice(src, Announce{ new = lc.registerDevice(src, Announce{
ID: []byte{42, 10, 20, 30, 40, 50, 60, 70, 80, 90}, ID: protocol.DeviceID{42, 10, 20, 30, 40, 50, 60, 70, 80, 90},
Addresses: []string{"tcp://0.0.0.0:22000"}, Addresses: []string{"tcp://0.0.0.0:22000"},
InstanceID: 1234567890, InstanceID: 1234567890,
}) })
@ -70,7 +70,7 @@ func TestLocalInstanceIDShouldTriggerNew(t *testing.T) {
} }
new = lc.registerDevice(src, Announce{ new = lc.registerDevice(src, Announce{
ID: []byte{10, 20, 30, 40, 50, 60, 70, 80, 90}, ID: protocol.DeviceID{10, 20, 30, 40, 50, 60, 70, 80, 90},
Addresses: []string{"tcp://0.0.0.0:22000"}, Addresses: []string{"tcp://0.0.0.0:22000"},
InstanceID: 91234567890, InstanceID: 91234567890,
}) })

View File

@ -8,7 +8,6 @@ package model
import ( import (
"bufio" "bufio"
"bytes"
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"errors" "errors"
@ -791,7 +790,7 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
var startSequence int64 var startSequence int64
for _, dev := range folder.Devices { for _, dev := range folder.Devices {
if bytes.Equal(dev.ID, m.id[:]) { if dev.ID == m.id {
// This is the other side's description of what it knows // This is the other side's description of what it knows
// about us. Lets check to see if we can start sending index // about us. Lets check to see if we can start sending index
// updates directly or need to send the index from start... // updates directly or need to send the index from start...
@ -822,7 +821,7 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
l.Infof("Device %v folder %q has mismatching index ID for us (%v != %v)", deviceID, folder.ID, dev.IndexID, myIndexID) l.Infof("Device %v folder %q has mismatching index ID for us (%v != %v)", deviceID, folder.ID, dev.IndexID, myIndexID)
startSequence = 0 startSequence = 0
} }
} else if bytes.Equal(dev.ID, deviceID[:]) && dev.IndexID != 0 { } else if dev.ID == deviceID && dev.IndexID != 0 {
// This is the other side's description of themselves. We // This is the other side's description of themselves. We
// check to see that it matches the IndexID we have on file, // check to see that it matches the IndexID we have on file,
// otherwise we drop our old index data and expect to get a // otherwise we drop our old index data and expect to get a
@ -885,10 +884,7 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
nextDevice: nextDevice:
for _, device := range folder.Devices { for _, device := range folder.Devices {
var id protocol.DeviceID if _, ok := m.cfg.Devices()[device.ID]; !ok {
copy(id[:], device.ID)
if _, ok := m.cfg.Devices()[id]; !ok {
// The device is currently unknown. Add it to the config. // The device is currently unknown. Add it to the config.
addresses := []string{"dynamic"} addresses := []string{"dynamic"}
@ -898,9 +894,9 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
} }
} }
l.Infof("Adding device %v to config (vouched for by introducer %v)", id, deviceID) l.Infof("Adding device %v to config (vouched for by introducer %v)", device.ID, deviceID)
newDeviceCfg := config.DeviceConfiguration{ newDeviceCfg := config.DeviceConfiguration{
DeviceID: id, DeviceID: device.ID,
Name: device.Name, Name: device.Name,
Compression: m.cfg.Devices()[deviceID].Compression, Compression: m.cfg.Devices()[deviceID].Compression,
Addresses: addresses, Addresses: addresses,
@ -909,7 +905,7 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
// The introducers' introducers are also our introducers. // The introducers' introducers are also our introducers.
if device.Introducer { if device.Introducer {
l.Infof("Device %v is now also an introducer", id) l.Infof("Device %v is now also an introducer", device.ID)
newDeviceCfg.Introducer = true newDeviceCfg.Introducer = true
} }
@ -917,7 +913,7 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
changed = true changed = true
} }
for _, er := range m.deviceFolders[id] { for _, er := range m.deviceFolders[device.ID] {
if er == folder.ID { if er == folder.ID {
// We already share the folder with this device, so // We already share the folder with this device, so
// nothing to do. // nothing to do.
@ -928,14 +924,14 @@ func (m *Model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
// We don't yet share this folder with this device. Add the device // We don't yet share this folder with this device. Add the device
// to sharing list of the folder. // to sharing list of the folder.
l.Infof("Adding device %v to share %q (vouched for by introducer %v)", id, folder.ID, deviceID) l.Infof("Adding device %v to share %q (vouched for by introducer %v)", device.ID, folder.ID, deviceID)
m.deviceFolders[id] = append(m.deviceFolders[id], folder.ID) m.deviceFolders[device.ID] = append(m.deviceFolders[device.ID], folder.ID)
m.folderDevices[folder.ID] = append(m.folderDevices[folder.ID], id) m.folderDevices[folder.ID] = append(m.folderDevices[folder.ID], device.ID)
folderCfg := m.cfg.Folders()[folder.ID] folderCfg := m.cfg.Folders()[folder.ID]
folderCfg.Devices = append(folderCfg.Devices, config.FolderDeviceConfiguration{ folderCfg.Devices = append(folderCfg.Devices, config.FolderDeviceConfiguration{
DeviceID: id, DeviceID: device.ID,
}) })
m.cfg.SetFolder(folderCfg) m.cfg.SetFolder(folderCfg)
@ -1898,7 +1894,7 @@ func (m *Model) generateClusterConfig(device protocol.DeviceID) protocol.Cluster
} }
protocolDevice := protocol.Device{ protocolDevice := protocol.Device{
ID: device[:], ID: device,
Name: deviceCfg.Name, Name: deviceCfg.Name,
Addresses: deviceCfg.Addresses, Addresses: deviceCfg.Addresses,
Compression: deviceCfg.Compression, Compression: deviceCfg.Compression,

View File

@ -444,13 +444,13 @@ func TestClusterConfig(t *testing.T) {
if l := len(r.Devices); l != 2 { if l := len(r.Devices); l != 2 {
t.Errorf("Incorrect number of devices %d != 2", l) t.Errorf("Incorrect number of devices %d != 2", l)
} }
if id := r.Devices[0].ID; !bytes.Equal(id, device1[:]) { if id := r.Devices[0].ID; id != device1 {
t.Errorf("Incorrect device ID %x != %x", id, device1) t.Errorf("Incorrect device ID %x != %x", id, device1)
} }
if !r.Devices[0].Introducer { if !r.Devices[0].Introducer {
t.Error("Device1 should be flagged as Introducer") t.Error("Device1 should be flagged as Introducer")
} }
if id := r.Devices[1].ID; !bytes.Equal(id, device2[:]) { if id := r.Devices[1].ID; id != device2 {
t.Errorf("Incorrect device ID %x != %x", id, device2) t.Errorf("Incorrect device ID %x != %x", id, device2)
} }
if r.Devices[1].Introducer { if r.Devices[1].Introducer {
@ -464,13 +464,13 @@ func TestClusterConfig(t *testing.T) {
if l := len(r.Devices); l != 2 { if l := len(r.Devices); l != 2 {
t.Errorf("Incorrect number of devices %d != 2", l) t.Errorf("Incorrect number of devices %d != 2", l)
} }
if id := r.Devices[0].ID; !bytes.Equal(id, device1[:]) { if id := r.Devices[0].ID; id != device1 {
t.Errorf("Incorrect device ID %x != %x", id, device1) t.Errorf("Incorrect device ID %x != %x", id, device1)
} }
if !r.Devices[0].Introducer { if !r.Devices[0].Introducer {
t.Error("Device1 should be flagged as Introducer") t.Error("Device1 should be flagged as Introducer")
} }
if id := r.Devices[1].ID; !bytes.Equal(id, device2[:]) { if id := r.Devices[1].ID; id != device2 {
t.Errorf("Incorrect device ID %x != %x", id, device2) t.Errorf("Incorrect device ID %x != %x", id, device2)
} }
if r.Devices[1].Introducer { if r.Devices[1].Introducer {
@ -1565,8 +1565,8 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
{ {
ID: "default", ID: "default",
Devices: []protocol.Device{ Devices: []protocol.Device{
{ID: device1[:]}, {ID: device1},
{ID: device2[:]}, {ID: device2},
}, },
}, },
}, },
@ -1576,8 +1576,8 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
{ {
ID: "default", ID: "default",
Devices: []protocol.Device{ Devices: []protocol.Device{
{ID: device1[:]}, {ID: device1},
{ID: device2[:]}, {ID: device2},
}, },
}, },
}, },
@ -1751,8 +1751,8 @@ func addFakeConn(m *Model, dev protocol.DeviceID) {
{ {
ID: "default", ID: "default",
Devices: []protocol.Device{ Devices: []protocol.Device{
{ID: device1[:]}, {ID: device1},
{ID: device2[:]}, {ID: device2},
}, },
}, },
}, },

View File

@ -255,7 +255,7 @@ func (*Folder) ProtoMessage() {}
func (*Folder) Descriptor() ([]byte, []int) { return fileDescriptorBep, []int{3} } func (*Folder) Descriptor() ([]byte, []int) { return fileDescriptorBep, []int{3} }
type Device struct { type Device struct {
ID []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` ID DeviceID `protobuf:"bytes,1,opt,name=id,proto3,customtype=DeviceID" json:"id"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Addresses []string `protobuf:"bytes,3,rep,name=addresses" json:"addresses,omitempty"` Addresses []string `protobuf:"bytes,3,rep,name=addresses" json:"addresses,omitempty"`
Compression Compression `protobuf:"varint,4,opt,name=compression,proto3,enum=protocol.Compression" json:"compression,omitempty"` Compression Compression `protobuf:"varint,4,opt,name=compression,proto3,enum=protocol.Compression" json:"compression,omitempty"`
@ -621,12 +621,14 @@ func (m *Device) MarshalTo(data []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.ID) > 0 { data[i] = 0xa
data[i] = 0xa i++
i++ i = encodeVarintBep(data, i, uint64(m.ID.ProtoSize()))
i = encodeVarintBep(data, i, uint64(len(m.ID))) n1, err := m.ID.MarshalTo(data[i:])
i += copy(data[i:], m.ID) if err != nil {
return 0, err
} }
i += n1
if len(m.Name) > 0 { if len(m.Name) > 0 {
data[i] = 0x12 data[i] = 0x12
i++ i++
@ -828,11 +830,11 @@ func (m *FileInfo) MarshalTo(data []byte) (int, error) {
data[i] = 0x4a data[i] = 0x4a
i++ i++
i = encodeVarintBep(data, i, uint64(m.Version.ProtoSize())) i = encodeVarintBep(data, i, uint64(m.Version.ProtoSize()))
n1, err := m.Version.MarshalTo(data[i:]) n2, err := m.Version.MarshalTo(data[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n1 i += n2
if m.Sequence != 0 { if m.Sequence != 0 {
data[i] = 0x50 data[i] = 0x50
i++ i++
@ -1112,11 +1114,11 @@ func (m *FileDownloadProgressUpdate) MarshalTo(data []byte) (int, error) {
data[i] = 0x1a data[i] = 0x1a
i++ i++
i = encodeVarintBep(data, i, uint64(m.Version.ProtoSize())) i = encodeVarintBep(data, i, uint64(m.Version.ProtoSize()))
n2, err := m.Version.MarshalTo(data[i:]) n3, err := m.Version.MarshalTo(data[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n2 i += n3
if len(m.BlockIndexes) > 0 { if len(m.BlockIndexes) > 0 {
for _, num := range m.BlockIndexes { for _, num := range m.BlockIndexes {
data[i] = 0x20 data[i] = 0x20
@ -1273,10 +1275,8 @@ func (m *Folder) ProtoSize() (n int) {
func (m *Device) ProtoSize() (n int) { func (m *Device) ProtoSize() (n int) {
var l int var l int
_ = l _ = l
l = len(m.ID) l = m.ID.ProtoSize()
if l > 0 { n += 1 + l + sovBep(uint64(l))
n += 1 + l + sovBep(uint64(l))
}
l = len(m.Name) l = len(m.Name)
if l > 0 { if l > 0 {
n += 1 + l + sovBep(uint64(l)) n += 1 + l + sovBep(uint64(l))
@ -2114,9 +2114,8 @@ func (m *Device) Unmarshal(data []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.ID = append(m.ID[:0], data[iNdEx:postIndex]...) if err := m.ID.Unmarshal(data[iNdEx:postIndex]); err != nil {
if m.ID == nil { return err
m.ID = []byte{}
} }
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
@ -3954,105 +3953,105 @@ var (
) )
var fileDescriptorBep = []byte{ var fileDescriptorBep = []byte{
// 1589 bytes of a gzipped FileDescriptorProto // 1598 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x4f, 0x6f, 0xdb, 0x46, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xcd, 0x6e, 0xdb, 0xc6,
0x16, 0xb7, 0x24, 0xea, 0xdf, 0x48, 0x76, 0xe4, 0x89, 0xe3, 0x68, 0x19, 0xc7, 0xf6, 0x32, 0x09, 0x16, 0xb6, 0x24, 0xea, 0x6f, 0x24, 0x3b, 0xf2, 0xc4, 0x71, 0x74, 0x19, 0xc7, 0xf6, 0x65, 0x92,
0xd6, 0x2b, 0x6c, 0x9c, 0xdd, 0x64, 0x77, 0x03, 0x14, 0x68, 0x01, 0x59, 0xa2, 0x1d, 0x21, 0x32, 0x7b, 0x7d, 0x85, 0x1b, 0xe7, 0xde, 0xa4, 0x6d, 0x80, 0x02, 0x2d, 0x20, 0x4b, 0xb4, 0x23, 0x44,
0xa5, 0x50, 0x92, 0xd3, 0xf4, 0x50, 0x41, 0x12, 0x47, 0x32, 0x11, 0x8a, 0xa3, 0x92, 0x54, 0x12, 0xa6, 0x14, 0x4a, 0x72, 0x9a, 0x2e, 0x2a, 0x48, 0xe2, 0x48, 0x26, 0x42, 0x71, 0x54, 0x52, 0x4a,
0xf7, 0x23, 0xb4, 0x5f, 0xa0, 0x97, 0x02, 0x41, 0x6e, 0xbd, 0xf7, 0x43, 0xe4, 0x18, 0xe4, 0xd8, 0xe2, 0x3e, 0x42, 0xfb, 0x02, 0xdd, 0x14, 0x08, 0xba, 0xeb, 0xb6, 0xe8, 0x43, 0x64, 0x19, 0x64,
0x43, 0xd0, 0xba, 0x97, 0x7e, 0x81, 0xde, 0xfb, 0xf8, 0x86, 0x94, 0x28, 0xff, 0x29, 0x72, 0xe8, 0xd9, 0x45, 0xd0, 0xa6, 0x9b, 0xbe, 0x40, 0xf7, 0x3d, 0x3c, 0x43, 0x52, 0x94, 0x7f, 0x8a, 0x2c,
0xc1, 0xd0, 0xcc, 0x7b, 0xbf, 0x99, 0x37, 0xf3, 0x7b, 0xbf, 0xf7, 0x86, 0x26, 0xd9, 0x3e, 0x9b, 0xba, 0x30, 0x34, 0x73, 0xce, 0x37, 0xe7, 0xcc, 0xf9, 0xce, 0xcf, 0xd0, 0x24, 0xdb, 0x67, 0x93,
0xec, 0x4e, 0x1c, 0xee, 0x71, 0x9a, 0xc1, 0x9f, 0x01, 0xb7, 0xe4, 0xbb, 0x23, 0xd3, 0x3b, 0x9e, 0xdd, 0x89, 0xc3, 0xa7, 0x9c, 0x66, 0xf0, 0x67, 0xc0, 0x2d, 0xf9, 0xf6, 0xc8, 0x9c, 0x1e, 0xcf,
0xf6, 0x77, 0x07, 0x7c, 0x7c, 0x6f, 0xc4, 0x47, 0xfc, 0x1e, 0x7a, 0xfa, 0xd3, 0x21, 0xce, 0x70, 0xfa, 0xbb, 0x03, 0x3e, 0xbe, 0x33, 0xe2, 0x23, 0x7e, 0x07, 0x35, 0xfd, 0xd9, 0x10, 0x77, 0xb8,
0x82, 0x23, 0xb1, 0x50, 0x99, 0x90, 0xe4, 0x23, 0x66, 0x59, 0x9c, 0x6e, 0x91, 0x9c, 0xc1, 0x5e, 0xc1, 0x95, 0x38, 0xa8, 0x4c, 0x48, 0xf2, 0x01, 0xb3, 0x2c, 0x4e, 0xb7, 0x48, 0xce, 0x60, 0xcf,
0x98, 0x03, 0xd6, 0xb5, 0x7b, 0x63, 0x56, 0x8c, 0x6d, 0xc7, 0x76, 0xb2, 0x3a, 0x11, 0x26, 0x0d, 0xcc, 0x01, 0xeb, 0xda, 0xbd, 0x31, 0x2b, 0xc6, 0xb6, 0x63, 0x3b, 0x59, 0x9d, 0x08, 0x91, 0x06,
0x2c, 0x3e, 0x60, 0x60, 0x99, 0xcc, 0xf6, 0x04, 0x20, 0x2e, 0x00, 0xc2, 0x84, 0x80, 0x3b, 0x64, 0x12, 0x0f, 0x30, 0xb0, 0x4c, 0x66, 0x4f, 0x05, 0x20, 0x2e, 0x00, 0x42, 0x84, 0x80, 0x5b, 0x64,
0x25, 0x00, 0xbc, 0x60, 0x8e, 0x6b, 0x72, 0xbb, 0x98, 0x40, 0xcc, 0xb2, 0xb0, 0x1e, 0x09, 0xa3, 0xc5, 0x07, 0x3c, 0x63, 0x8e, 0x6b, 0x72, 0xbb, 0x98, 0x40, 0xcc, 0xb2, 0x90, 0x1e, 0x09, 0xa1,
0xe2, 0x92, 0xd4, 0x23, 0xd6, 0x33, 0x98, 0x43, 0xff, 0x49, 0x24, 0xef, 0x64, 0x22, 0x62, 0xad, 0xe2, 0x92, 0xd4, 0x03, 0xd6, 0x33, 0x98, 0x43, 0xff, 0x43, 0xa4, 0xe9, 0xc9, 0x44, 0xf8, 0x5a,
0xdc, 0xbf, 0xb6, 0x1b, 0xde, 0x61, 0xf7, 0x90, 0xb9, 0x6e, 0x6f, 0xc4, 0xda, 0xe0, 0xd4, 0x11, 0xb9, 0x7b, 0x65, 0x37, 0x88, 0x61, 0xf7, 0x90, 0xb9, 0x6e, 0x6f, 0xc4, 0xda, 0xa0, 0xd4, 0x11,
0x42, 0x3f, 0x83, 0xe0, 0x7c, 0x3c, 0x71, 0xc0, 0xe1, 0x6f, 0x1c, 0xc7, 0x15, 0x1b, 0xe7, 0x56, 0x42, 0x3f, 0x05, 0xe7, 0x7c, 0x3c, 0x71, 0x40, 0xe1, 0x19, 0x8e, 0xe3, 0x89, 0x8d, 0x33, 0x27,
0x54, 0xe6, 0x18, 0x3d, 0xba, 0x40, 0x29, 0x93, 0xe5, 0x8a, 0x35, 0x75, 0x3d, 0xe6, 0x54, 0xb8, 0x2a, 0x73, 0x8c, 0x1e, 0x3d, 0xa0, 0x94, 0xc9, 0x72, 0xc5, 0x9a, 0xb9, 0x53, 0xe6, 0x54, 0xb8,
0x3d, 0x34, 0x47, 0xf4, 0xdf, 0x24, 0x3d, 0xe4, 0x16, 0x9c, 0xc2, 0x85, 0xf0, 0x89, 0x9d, 0xdc, 0x3d, 0x34, 0x47, 0xf4, 0x7f, 0x24, 0x3d, 0xe4, 0x16, 0xdc, 0xc2, 0x05, 0xf7, 0x89, 0x9d, 0xdc,
0xfd, 0xc2, 0x7c, 0xb3, 0x7d, 0x74, 0xec, 0x49, 0x6f, 0x3f, 0x6c, 0x2d, 0xe9, 0x21, 0x4c, 0xf9, 0xdd, 0xc2, 0xdc, 0xd8, 0x3e, 0x2a, 0xf6, 0xa4, 0x57, 0x6f, 0xb7, 0x96, 0xf4, 0x00, 0xa6, 0x7c,
0x36, 0x4e, 0x52, 0xc2, 0x43, 0xd7, 0x49, 0xdc, 0x34, 0x04, 0x45, 0x7b, 0xa9, 0xd3, 0x0f, 0x5b, 0x13, 0x27, 0x29, 0xa1, 0xa1, 0xeb, 0x24, 0x6e, 0x1a, 0x82, 0xa2, 0xbd, 0xd4, 0xbb, 0xb7, 0x5b,
0xf1, 0x5a, 0x55, 0x07, 0x0b, 0x5d, 0x23, 0x49, 0xab, 0xd7, 0x67, 0x56, 0x40, 0x8e, 0x98, 0xd0, 0xf1, 0x5a, 0x55, 0x07, 0x09, 0x5d, 0x23, 0x49, 0xab, 0xd7, 0x67, 0x96, 0x4f, 0x8e, 0xd8, 0xd0,
0x1b, 0x24, 0xeb, 0xc0, 0x85, 0xbb, 0xdc, 0xb6, 0x4e, 0x90, 0x92, 0x8c, 0x9e, 0xf1, 0x0d, 0x0d, 0x6b, 0x24, 0xeb, 0x40, 0xc0, 0x5d, 0x6e, 0x5b, 0x27, 0x48, 0x49, 0x46, 0xcf, 0x78, 0x82, 0x06,
0x98, 0xd3, 0xbb, 0x84, 0x9a, 0x23, 0x9b, 0x3b, 0xac, 0x3b, 0x61, 0xce, 0xd8, 0xc4, 0xd3, 0xba, 0xec, 0xe9, 0x6d, 0x42, 0xcd, 0x91, 0xcd, 0x1d, 0xd6, 0x9d, 0x30, 0x67, 0x6c, 0xe2, 0x6d, 0xdd,
0x45, 0x09, 0x51, 0xab, 0xc2, 0xd3, 0x9c, 0x3b, 0xe8, 0x2d, 0xb2, 0x1c, 0xc0, 0x0d, 0x66, 0x31, 0xa2, 0x84, 0xa8, 0x55, 0xa1, 0x69, 0xce, 0x15, 0xf4, 0x06, 0x59, 0xf6, 0xe1, 0x06, 0xb3, 0xd8,
0x8f, 0x15, 0x93, 0x88, 0xcc, 0x0b, 0x63, 0x15, 0x6d, 0x70, 0xb7, 0x35, 0xc3, 0x74, 0x7b, 0x7d, 0x94, 0x15, 0x93, 0x88, 0xcc, 0x0b, 0x61, 0x15, 0x65, 0x10, 0xdb, 0x9a, 0x61, 0xba, 0xbd, 0xbe,
0x8b, 0x75, 0x3d, 0x36, 0x9e, 0x74, 0x4d, 0xdb, 0x60, 0xaf, 0x98, 0x5b, 0x4c, 0x21, 0x96, 0x06, 0xc5, 0xba, 0x53, 0x36, 0x9e, 0x74, 0x4d, 0xdb, 0x60, 0x2f, 0x98, 0x5b, 0x4c, 0x21, 0x96, 0xfa,
0xbe, 0x36, 0xb8, 0x6a, 0xc2, 0xe3, 0xb3, 0x21, 0x32, 0xed, 0x16, 0x0b, 0x67, 0xd9, 0xa8, 0xa2, 0xba, 0x36, 0xa8, 0x6a, 0x42, 0xe3, 0xb1, 0x21, 0x32, 0xed, 0x16, 0x0b, 0xa7, 0xd9, 0xa8, 0xa2,
0x23, 0x64, 0x23, 0x80, 0x29, 0x6f, 0x80, 0x0d, 0xe1, 0x89, 0xb0, 0x91, 0x5f, 0x60, 0x83, 0x12, 0x22, 0x60, 0xc3, 0x87, 0x29, 0x3f, 0x02, 0x1b, 0x42, 0x43, 0xff, 0x15, 0xb2, 0x91, 0xdf, 0x5b,
0x29, 0xa2, 0x14, 0x1c, 0xd3, 0x0d, 0x92, 0xed, 0x19, 0x86, 0x9f, 0x15, 0x08, 0x95, 0x80, 0x50, 0xf7, 0x50, 0x3f, 0xbf, 0xdd, 0xca, 0x08, 0x5d, 0xad, 0x1a, 0x61, 0x87, 0x12, 0x29, 0x52, 0x39,
0x59, 0x7d, 0x6e, 0xa0, 0x0f, 0x17, 0xb3, 0x2c, 0x9d, 0xd5, 0xc5, 0x65, 0xe9, 0xf5, 0x29, 0x1e, 0xb8, 0xa6, 0x1b, 0x24, 0xdb, 0x33, 0x0c, 0x2f, 0x4b, 0xe0, 0x3a, 0x01, 0xae, 0xb3, 0xfa, 0x5c,
0x30, 0x27, 0x50, 0x66, 0x12, 0xe3, 0x65, 0x7c, 0x03, 0xea, 0xf2, 0xef, 0x24, 0x3f, 0xee, 0xbd, 0x40, 0xef, 0x2f, 0x66, 0x5d, 0x3a, 0x5d, 0x27, 0x17, 0xa5, 0xdb, 0xa3, 0x7c, 0xc0, 0x1c, 0xbf,
0xea, 0xba, 0xec, 0xab, 0x29, 0xb3, 0x07, 0x0c, 0x69, 0x48, 0xe8, 0x39, 0xb0, 0xb5, 0x02, 0x13, 0x52, 0x93, 0xe8, 0x2f, 0xe3, 0x09, 0xb0, 0x4e, 0xff, 0x49, 0xf2, 0xe3, 0xde, 0x8b, 0xae, 0xcb,
0xdd, 0x24, 0xc4, 0xb4, 0x3d, 0x87, 0x1b, 0x53, 0x58, 0x55, 0x4c, 0x23, 0x4f, 0x11, 0x0b, 0xfd, 0xbe, 0x9c, 0x31, 0x7b, 0xc0, 0x90, 0x96, 0x84, 0x9e, 0x03, 0x59, 0xcb, 0x17, 0xd1, 0x4d, 0x42,
0x1f, 0xc9, 0x20, 0x89, 0x5d, 0xb8, 0x68, 0x06, 0xbc, 0xd2, 0x9e, 0xec, 0xd3, 0xf1, 0xd3, 0x87, 0x4c, 0x7b, 0xea, 0x70, 0x63, 0x06, 0xa7, 0x8a, 0x69, 0xe4, 0x2d, 0x22, 0xa1, 0x1f, 0x92, 0x0c,
0xad, 0x34, 0x52, 0x58, 0xab, 0x9e, 0xce, 0x87, 0x7a, 0x1a, 0xb1, 0x35, 0x43, 0x69, 0x90, 0x24, 0x92, 0xda, 0x85, 0xc0, 0x33, 0xa0, 0x95, 0xf6, 0x64, 0x3f, 0xf0, 0x34, 0x52, 0x8a, 0x71, 0x07,
0xda, 0x80, 0xa2, 0x94, 0x90, 0x51, 0x50, 0x57, 0xc1, 0x8c, 0xee, 0x92, 0xe4, 0xd0, 0xb4, 0x80, 0x4b, 0x3d, 0x8d, 0xd8, 0x9a, 0xa1, 0x34, 0x48, 0x12, 0x65, 0x50, 0x40, 0x29, 0x51, 0x56, 0x7e,
0x8a, 0x38, 0xb2, 0x4e, 0x23, 0x1a, 0x04, 0x73, 0xcd, 0x1e, 0xf2, 0x80, 0x77, 0x01, 0x53, 0x3a, 0x9f, 0xf9, 0x3b, 0xba, 0x4b, 0x92, 0x43, 0xd3, 0x02, 0x2a, 0xe2, 0x98, 0x05, 0x1a, 0xa9, 0x49,
0x24, 0x87, 0x1b, 0x76, 0x26, 0x46, 0xcf, 0x63, 0x7f, 0xd9, 0xb6, 0x6f, 0x12, 0x24, 0x13, 0x7a, 0x10, 0xd7, 0xec, 0x21, 0xf7, 0xf3, 0x20, 0x60, 0x4a, 0x87, 0xe4, 0xd0, 0x60, 0x67, 0x62, 0xf4,
0x66, 0x69, 0x8b, 0x45, 0xd2, 0x56, 0x0a, 0x2a, 0x55, 0xd4, 0xdd, 0xfa, 0xf9, 0xfd, 0x22, 0xa5, 0x20, 0xf1, 0x7f, 0x97, 0xd9, 0xef, 0x13, 0x24, 0x13, 0x68, 0xc2, 0xb4, 0xc5, 0x22, 0x69, 0x2b,
0x0a, 0xeb, 0x5d, 0xf3, 0x6b, 0x86, 0x4a, 0x4f, 0xe8, 0x38, 0xa6, 0xdb, 0x24, 0x77, 0x56, 0xde, 0xf9, 0x9d, 0x2b, 0xfa, 0x70, 0xfd, 0xac, 0xbd, 0x48, 0xeb, 0xc2, 0x79, 0xd7, 0xfc, 0x8a, 0x61,
0xcb, 0x7a, 0xd4, 0x44, 0x6f, 0x12, 0x32, 0xe6, 0x86, 0x39, 0x34, 0x99, 0xd1, 0x75, 0x31, 0x85, 0xe5, 0x27, 0x74, 0x5c, 0xd3, 0x6d, 0x92, 0x3b, 0x5d, 0xee, 0xcb, 0x7a, 0x54, 0x44, 0xaf, 0x13,
0x09, 0x3d, 0x1b, 0x5a, 0x5a, 0xb4, 0xe8, 0x0b, 0xd4, 0x17, 0xb7, 0x11, 0xa8, 0x38, 0x9c, 0xfa, 0x32, 0xe6, 0x86, 0x39, 0x34, 0x99, 0xd1, 0x75, 0x31, 0x85, 0x09, 0x3d, 0x1b, 0x48, 0x5a, 0xb4,
0x1e, 0xd3, 0x7e, 0xd1, 0xb3, 0x20, 0x33, 0x22, 0x6f, 0xe1, 0xd4, 0xef, 0x47, 0x36, 0x5f, 0x28, 0xe8, 0x15, 0xac, 0x57, 0xec, 0x86, 0x5f, 0xd5, 0xc1, 0xd6, 0xd3, 0x98, 0xf6, 0xb3, 0x9e, 0x05,
0xab, 0x0c, 0x02, 0x96, 0x6d, 0x1e, 0x2d, 0x29, 0xd0, 0x7e, 0xd8, 0xaf, 0xb2, 0xe0, 0x5f, 0xd0, 0x99, 0x11, 0x79, 0x0b, 0xb6, 0xde, 0x7c, 0xb2, 0xf9, 0x42, 0x9b, 0x65, 0x10, 0xb0, 0x6c, 0xf3,
0xfe, 0x11, 0x1b, 0x78, 0x7c, 0xd6, 0x09, 0x02, 0x18, 0x95, 0x49, 0x66, 0x26, 0x26, 0x82, 0x27, 0x68, 0x8b, 0x41, 0x2f, 0x04, 0xf3, 0x2b, 0x0b, 0xfa, 0x85, 0x5e, 0x38, 0x62, 0x83, 0x29, 0x0f,
0x9d, 0xcd, 0xfd, 0x2e, 0x39, 0xbb, 0x07, 0x44, 0xcc, 0x81, 0x3b, 0xa9, 0xcf, 0xae, 0xa6, 0xb9, 0x27, 0x83, 0x0f, 0xa3, 0x32, 0xc9, 0x84, 0xc5, 0x44, 0xf0, 0xa6, 0xe1, 0xde, 0x9b, 0x9a, 0x61,
0xf4, 0x3f, 0x24, 0xb5, 0x67, 0xf1, 0xc1, 0xf3, 0xb0, 0xd2, 0xae, 0xce, 0xa3, 0xa1, 0x3d, 0x92, 0x1c, 0xe0, 0x31, 0x07, 0xea, 0xa4, 0x1e, 0x86, 0xa6, 0xb9, 0xf4, 0xff, 0x24, 0xb5, 0x67, 0xf1,
0x9d, 0x54, 0x1f, 0x81, 0x9f, 0x48, 0xdf, 0xbd, 0xde, 0x5a, 0x52, 0x9e, 0x90, 0xec, 0x0c, 0xe0, 0xc1, 0xd3, 0xa0, 0xf3, 0x2e, 0xcf, 0xbd, 0xa1, 0x3c, 0x92, 0x9d, 0x54, 0x1f, 0x81, 0x1f, 0x4b,
0x67, 0x9e, 0x0f, 0x87, 0x2e, 0xf3, 0x30, 0x4d, 0x09, 0x3d, 0x98, 0xcd, 0xc8, 0x8f, 0x63, 0x5c, 0xdf, 0xbe, 0xdc, 0x5a, 0x52, 0x1e, 0x91, 0x6c, 0x08, 0xf0, 0x32, 0xcf, 0x87, 0x43, 0x97, 0x4d,
0x41, 0x3e, 0xd8, 0x8e, 0x7b, 0xee, 0x31, 0x26, 0x24, 0xaf, 0xe3, 0x38, 0xd8, 0xf2, 0x53, 0x92, 0x31, 0x4d, 0x09, 0xdd, 0xdf, 0x85, 0xe4, 0xc7, 0xd1, 0xaf, 0x20, 0x1f, 0x64, 0xc7, 0x3d, 0xf7,
0x12, 0x37, 0xa4, 0x0f, 0x48, 0x66, 0xc0, 0xa7, 0xb6, 0x37, 0xef, 0x87, 0xab, 0xd1, 0xb2, 0x43, 0x18, 0x13, 0x92, 0xd7, 0x71, 0xed, 0x9b, 0xfc, 0x84, 0xa4, 0x44, 0x84, 0xf4, 0x1e, 0xc9, 0x0c,
0x4f, 0x70, 0xaa, 0x19, 0x50, 0xd9, 0x27, 0xe9, 0xc0, 0x05, 0x5c, 0x87, 0x3d, 0x40, 0xda, 0xbb, 0xf8, 0xcc, 0x9e, 0xce, 0xe7, 0xe3, 0x6a, 0xb4, 0xed, 0x50, 0xe3, 0xdf, 0x2a, 0x04, 0x2a, 0xfb,
0x16, 0x96, 0x46, 0xeb, 0x98, 0x3b, 0x1e, 0x96, 0x46, 0xa4, 0x41, 0x42, 0x6e, 0xa6, 0xe2, 0x7c, 0x24, 0xed, 0xab, 0x80, 0xeb, 0x60, 0x26, 0x48, 0x7b, 0x57, 0x82, 0xd6, 0x68, 0x1d, 0x73, 0x67,
0x92, 0x2e, 0x26, 0xca, 0x8f, 0x31, 0x92, 0xd6, 0x7d, 0x02, 0x5d, 0x2f, 0xd2, 0x4c, 0x92, 0x0b, 0xba, 0x30, 0x12, 0x60, 0x60, 0x42, 0x6e, 0x66, 0xe2, 0x7e, 0x92, 0x2e, 0x36, 0xca, 0x4f, 0x31,
0xcd, 0x64, 0x2e, 0xf5, 0xf8, 0x82, 0xd4, 0x43, 0xb5, 0x26, 0x22, 0x6a, 0x9d, 0x93, 0x23, 0x5d, 0x92, 0xd6, 0x3d, 0x02, 0xdd, 0x69, 0x64, 0xd4, 0x26, 0x17, 0x46, 0xed, 0xbc, 0xd4, 0xe3, 0x0b,
0x48, 0x4e, 0xf2, 0x02, 0x72, 0x52, 0x73, 0x72, 0x7c, 0xe1, 0x0c, 0x1d, 0x3e, 0xc6, 0xe6, 0xc9, 0xa5, 0x1e, 0x54, 0x6b, 0x22, 0x52, 0xad, 0x73, 0x72, 0xa4, 0x73, 0xc9, 0x49, 0x9e, 0x43, 0x4e,
0x9d, 0x9e, 0x73, 0x12, 0x28, 0x6b, 0xd9, 0xb7, 0xb6, 0x43, 0xa3, 0xd2, 0x25, 0x19, 0x9d, 0xb9, 0x6a, 0x4e, 0x8e, 0x57, 0x38, 0x43, 0x87, 0x8f, 0x71, 0x98, 0x72, 0xa7, 0xe7, 0x9c, 0xf8, 0x95,
0x13, 0xd0, 0x10, 0xbb, 0xf4, 0xd8, 0xb0, 0x3d, 0x54, 0x6a, 0x0f, 0x0f, 0x0d, 0xdb, 0xfb, 0x63, 0xb5, 0xec, 0x49, 0xdb, 0x81, 0x50, 0xe9, 0x92, 0x8c, 0xce, 0xdc, 0x09, 0xd4, 0x10, 0xbb, 0xf0,
0xfa, 0x0f, 0x22, 0x0d, 0xb8, 0x21, 0x8e, 0xbc, 0x12, 0xcd, 0xbf, 0xea, 0x38, 0x1c, 0xde, 0x27, 0xda, 0x60, 0x1e, 0x3a, 0xb5, 0x87, 0x97, 0x06, 0xf3, 0xde, 0x9a, 0xfe, 0x9b, 0x48, 0x03, 0x6e,
0x03, 0x2a, 0xc9, 0x07, 0xc0, 0xdb, 0x5c, 0xa8, 0xf2, 0x97, 0xb6, 0xc5, 0x7b, 0x46, 0xd3, 0xe1, 0x88, 0x2b, 0xaf, 0x44, 0xf3, 0xaf, 0x3a, 0x0e, 0x87, 0xf7, 0xca, 0x80, 0x4e, 0xf2, 0x00, 0xf0,
0x23, 0xbf, 0xd9, 0x5d, 0x5a, 0xf2, 0x55, 0x92, 0x9e, 0x62, 0x53, 0x08, 0x8b, 0xfe, 0xf6, 0x62, 0x56, 0x17, 0xaa, 0xfc, 0xb9, 0x6d, 0xf1, 0x9e, 0xd1, 0x74, 0xf8, 0xc8, 0x1b, 0x76, 0x17, 0xb6,
0x91, 0x9e, 0xdd, 0x48, 0x74, 0x90, 0x50, 0xd9, 0xc1, 0x52, 0xe5, 0x7d, 0x8c, 0xc8, 0x97, 0xa3, 0x7c, 0x95, 0xa4, 0x67, 0x38, 0x14, 0x82, 0xa6, 0xbf, 0xb9, 0xd8, 0xa4, 0xa7, 0x0d, 0x89, 0x09,
0x69, 0x8d, 0xe4, 0x04, 0xb2, 0x1b, 0x79, 0xb7, 0x77, 0x3e, 0x26, 0x10, 0xf6, 0x07, 0x32, 0x9d, 0x12, 0x54, 0xb6, 0x7f, 0x54, 0x79, 0x13, 0x23, 0xf2, 0xc5, 0x68, 0x5a, 0x23, 0x39, 0x81, 0xec,
0x8d, 0x2f, 0x7c, 0x1c, 0x22, 0x95, 0x98, 0xf8, 0xb8, 0x4a, 0x84, 0xe7, 0x10, 0x6b, 0x64, 0xf6, 0x46, 0xde, 0xf1, 0x9d, 0xf7, 0x71, 0x84, 0xf3, 0x81, 0xcc, 0xc2, 0xf5, 0xb9, 0x8f, 0x43, 0xa4,
0xc4, 0x49, 0x70, 0xf7, 0xa4, 0x9e, 0xef, 0x8b, 0x42, 0x41, 0x9b, 0x92, 0x22, 0x52, 0xd3, 0xb4, 0x13, 0x13, 0xef, 0xd7, 0x89, 0xf0, 0x3c, 0x62, 0x8f, 0x84, 0x4f, 0x9e, 0x04, 0xb1, 0x27, 0xf5,
0x47, 0xca, 0x16, 0x49, 0x56, 0x2c, 0x8e, 0xc9, 0x4a, 0xc1, 0xfb, 0xeb, 0x42, 0x98, 0x80, 0x43, 0x7c, 0x5f, 0x34, 0x0a, 0xca, 0x94, 0x14, 0x91, 0x9a, 0xa6, 0x3d, 0x52, 0xb6, 0x48, 0xb2, 0x62,
0x31, 0x2b, 0xbd, 0x8f, 0x93, 0x5c, 0xe4, 0xd3, 0x03, 0xce, 0xb3, 0x52, 0xa9, 0x77, 0x5a, 0x6d, 0x71, 0x4c, 0x56, 0x0a, 0xde, 0x63, 0x17, 0xdc, 0xf8, 0x1c, 0x8a, 0x5d, 0xe9, 0x4d, 0x9c, 0xe4,
0x55, 0xef, 0x56, 0x1a, 0xda, 0x7e, 0xed, 0xa0, 0xb0, 0x24, 0x6f, 0x7c, 0xf3, 0xfd, 0x76, 0x71, 0x22, 0x9f, 0x22, 0x70, 0x9f, 0x95, 0x4a, 0xbd, 0xd3, 0x6a, 0xab, 0x7a, 0xb7, 0xd2, 0xd0, 0xf6,
0x3c, 0x07, 0x2d, 0x7e, 0x55, 0x40, 0x88, 0x9a, 0x56, 0x55, 0x3f, 0x2f, 0xc4, 0xe4, 0x35, 0x00, 0x6b, 0x07, 0x85, 0x25, 0x79, 0xe3, 0xeb, 0xef, 0xb6, 0x8b, 0xe3, 0x39, 0x68, 0xf1, 0x2b, 0x03,
0x16, 0x22, 0x40, 0xf1, 0x10, 0xfc, 0x8b, 0xe4, 0x11, 0xd0, 0xed, 0x34, 0xab, 0xe5, 0xb6, 0x5a, 0x5c, 0xd4, 0xb4, 0xaa, 0xfa, 0x59, 0x21, 0x26, 0xaf, 0x01, 0xb0, 0x10, 0x01, 0x8a, 0x87, 0xe0,
0x88, 0xcb, 0x32, 0xe0, 0xd6, 0xcf, 0xe2, 0x02, 0xbe, 0x6f, 0x41, 0x5d, 0xa8, 0x4f, 0x3a, 0x6a, 0xbf, 0x24, 0x8f, 0x80, 0x6e, 0xa7, 0x59, 0x2d, 0xb7, 0xd5, 0x42, 0x5c, 0x96, 0x01, 0xb7, 0x7e,
0xab, 0x5d, 0x48, 0xc8, 0xeb, 0x00, 0xa4, 0x11, 0x60, 0x58, 0x31, 0x77, 0x40, 0x86, 0x6a, 0xab, 0x1a, 0xe7, 0xf3, 0x7d, 0x03, 0xfa, 0x42, 0x7d, 0xd4, 0x51, 0x5b, 0xed, 0x42, 0x42, 0x5e, 0x07,
0xd9, 0xd0, 0x5a, 0x6a, 0x41, 0x92, 0xaf, 0x03, 0xea, 0xea, 0x02, 0x2a, 0x50, 0xe8, 0xff, 0xc9, 0x20, 0x8d, 0x00, 0x83, 0x8e, 0xb9, 0x05, 0x65, 0xa8, 0xb6, 0x9a, 0x0d, 0xad, 0xa5, 0x16, 0x24,
0x6a, 0xb5, 0xf1, 0x54, 0xab, 0x37, 0xca, 0xd5, 0x6e, 0x53, 0x6f, 0x1c, 0xc0, 0x9a, 0x56, 0x21, 0xf9, 0x2a, 0xa0, 0x2e, 0x2f, 0xa0, 0xfc, 0x0a, 0xfd, 0x88, 0xac, 0x56, 0x1b, 0x8f, 0xb5, 0x7a,
0x29, 0x6f, 0x01, 0xfe, 0x46, 0x04, 0x7f, 0x4e, 0x70, 0x37, 0x81, 0xbd, 0x9a, 0x76, 0x50, 0x48, 0xa3, 0x5c, 0xed, 0x36, 0xf5, 0xc6, 0x01, 0x9c, 0x69, 0x15, 0x92, 0xf2, 0x16, 0xe0, 0xaf, 0x45,
0xc9, 0x57, 0x01, 0x7a, 0x25, 0x02, 0xf5, 0x49, 0xf5, 0x6f, 0x5c, 0xa9, 0x37, 0x20, 0x74, 0xfa, 0xf0, 0x67, 0x0a, 0xee, 0x3a, 0xb0, 0x57, 0xd3, 0x0e, 0x0a, 0x29, 0xf9, 0x32, 0x40, 0x2f, 0x45,
0xdc, 0x8d, 0x91, 0xec, 0xd2, 0x97, 0x84, 0x9e, 0xff, 0x38, 0xa3, 0xb7, 0x89, 0xa4, 0x35, 0x34, 0xa0, 0x1e, 0xa9, 0x5e, 0xc4, 0x95, 0x7a, 0x03, 0x5c, 0xa7, 0xcf, 0x44, 0x8c, 0x64, 0x97, 0xbe,
0x15, 0x08, 0xc5, 0xfb, 0x9f, 0x47, 0x68, 0xdc, 0x66, 0x54, 0x21, 0x89, 0xfa, 0x17, 0xff, 0x05, 0x20, 0xf4, 0xec, 0xc7, 0x1a, 0xbd, 0x49, 0x24, 0xad, 0xa1, 0xa9, 0x40, 0x28, 0xc6, 0x7f, 0x16,
0x32, 0xff, 0x06, 0xa0, 0x6b, 0xe7, 0x41, 0xe0, 0x2c, 0x71, 0x92, 0x8b, 0x6e, 0xac, 0x90, 0xcc, 0xa1, 0x71, 0x9b, 0x51, 0x85, 0x24, 0xea, 0x9f, 0x7f, 0x00, 0x64, 0xfe, 0x03, 0x40, 0x57, 0xce,
0xa1, 0xda, 0x2e, 0x03, 0xb9, 0x65, 0xd8, 0x1c, 0x8f, 0x14, 0xba, 0x0f, 0x99, 0xd7, 0xc3, 0x02, 0x82, 0x40, 0x59, 0xe2, 0x24, 0x17, 0x35, 0xac, 0x90, 0xcc, 0xa1, 0xda, 0x2e, 0x03, 0xb9, 0x65,
0xdc, 0x20, 0x49, 0x4d, 0x3d, 0x52, 0x75, 0xd8, 0x78, 0x15, 0x00, 0xcb, 0x21, 0x40, 0x63, 0xa0, 0x30, 0x8e, 0x57, 0x0a, 0xd4, 0x87, 0x6c, 0xda, 0xc3, 0x06, 0xdc, 0x20, 0x49, 0x4d, 0x3d, 0x52,
0x2b, 0xf8, 0x16, 0x48, 0x95, 0xeb, 0x4f, 0xcb, 0xcf, 0x5a, 0x90, 0x1c, 0x0a, 0xee, 0x95, 0xd0, 0x75, 0x30, 0xbc, 0x0a, 0x80, 0xe5, 0x00, 0xa0, 0x31, 0xa8, 0x2b, 0xf8, 0x16, 0x48, 0x95, 0xeb,
0x5d, 0xb6, 0x5e, 0xf6, 0x4e, 0xdc, 0xd2, 0xef, 0x31, 0x92, 0x8f, 0x3e, 0x7b, 0xb0, 0x40, 0xda, 0x8f, 0xcb, 0x4f, 0x5a, 0x90, 0x1c, 0x0a, 0xea, 0x95, 0x40, 0x5d, 0xb6, 0x9e, 0xf7, 0x4e, 0xdc,
0xaf, 0xd5, 0xd5, 0x30, 0x5c, 0xd4, 0xe7, 0x8f, 0xe9, 0x0e, 0xc9, 0x56, 0x6b, 0xba, 0x5a, 0x69, 0xd2, 0x1f, 0x31, 0x92, 0x8f, 0x3e, 0x7b, 0x70, 0x40, 0xda, 0xaf, 0xd5, 0xd5, 0xc0, 0x5d, 0x54,
0x37, 0xf4, 0x67, 0xe1, 0x5d, 0xa2, 0xa0, 0xaa, 0xe9, 0xa0, 0xb8, 0xfd, 0x8f, 0xc1, 0x7c, 0xeb, 0xe7, 0xad, 0xe9, 0x0e, 0xc9, 0x56, 0x6b, 0xba, 0x5a, 0x69, 0x37, 0xf4, 0x27, 0x41, 0x2c, 0x51,
0xd9, 0x61, 0xbd, 0xa6, 0x3d, 0xee, 0xe2, 0x8e, 0x71, 0xf9, 0x06, 0x80, 0xaf, 0x47, 0xc1, 0xad, 0x50, 0xd5, 0x74, 0xb0, 0xb8, 0xbd, 0x8f, 0xc3, 0x7c, 0xeb, 0xc9, 0x61, 0xbd, 0xa6, 0x3d, 0xec,
0x93, 0xb1, 0x65, 0xda, 0xcf, 0x71, 0xe3, 0x87, 0x64, 0x35, 0x84, 0xcf, 0x03, 0x24, 0xe4, 0x6d, 0xa2, 0xc5, 0xb8, 0x7c, 0x0d, 0xc0, 0x57, 0xa3, 0xe0, 0xd6, 0xc9, 0xd8, 0x32, 0xed, 0xa7, 0x68,
0x58, 0xb3, 0x71, 0xc1, 0x9a, 0x79, 0x9c, 0x07, 0xe4, 0x4a, 0xb8, 0xb0, 0xa3, 0x3d, 0xd6, 0x40, 0xf8, 0x3e, 0x59, 0x0d, 0xe0, 0x73, 0x07, 0x09, 0x79, 0x1b, 0xce, 0x6c, 0x9c, 0x73, 0x66, 0xee,
0x16, 0xa0, 0x9c, 0x4d, 0x58, 0x26, 0x5f, 0xb0, 0xac, 0x63, 0x3f, 0xb7, 0x41, 0x14, 0xa5, 0x1f, 0xe7, 0x1e, 0xb9, 0x14, 0x1c, 0xec, 0x68, 0x0f, 0x35, 0x28, 0x0b, 0xa8, 0x9c, 0x4d, 0x38, 0x26,
0x62, 0x24, 0x3b, 0xeb, 0x50, 0x3e, 0xcf, 0x5a, 0xa3, 0xab, 0xea, 0x7a, 0x43, 0x0f, 0x2f, 0x3e, 0x9f, 0x73, 0xac, 0x63, 0x3f, 0xb5, 0xa1, 0x28, 0x4a, 0x3f, 0xc4, 0x48, 0x36, 0x9c, 0x50, 0x1e,
0x73, 0x6a, 0x1c, 0x87, 0xf0, 0xe1, 0x95, 0x3e, 0x50, 0x35, 0x55, 0xaf, 0x55, 0xc2, 0x7a, 0x98, 0xcf, 0x5a, 0xa3, 0xab, 0xea, 0x7a, 0x43, 0x0f, 0x02, 0x0f, 0x95, 0x1a, 0xc7, 0x25, 0x7c, 0x78,
0x41, 0x0e, 0x98, 0xcd, 0x1c, 0x73, 0x00, 0xff, 0x02, 0xe4, 0x61, 0x9b, 0x56, 0xa7, 0xf2, 0x28, 0xa5, 0x0f, 0x54, 0x4d, 0xd5, 0x6b, 0x95, 0xa0, 0x1f, 0x42, 0xc8, 0x01, 0xb3, 0x99, 0x63, 0x0e,
0xbc, 0x31, 0x0a, 0x38, 0xb2, 0x55, 0x6b, 0x3a, 0x38, 0xc6, 0xdb, 0x96, 0xfc, 0xd2, 0x39, 0x2a, 0xe0, 0x5f, 0x82, 0x3c, 0x98, 0x69, 0x75, 0x2a, 0x0f, 0x82, 0x88, 0xb1, 0x80, 0x23, 0xa6, 0x5a,
0xd7, 0x6b, 0x55, 0x01, 0x4d, 0xc8, 0x45, 0x80, 0xae, 0xcd, 0xa0, 0x35, 0xf1, 0xec, 0xfb, 0xd8, 0xb3, 0xc1, 0x31, 0x46, 0x5b, 0xf2, 0x5a, 0xe7, 0xa8, 0x5c, 0xaf, 0x55, 0x05, 0x34, 0x21, 0x17,
0x92, 0x41, 0x36, 0xff, 0xbc, 0x17, 0xc1, 0x17, 0x49, 0xaa, 0xdc, 0x6c, 0xaa, 0x5a, 0x35, 0x3c, 0x01, 0xba, 0x16, 0x42, 0x6b, 0xe2, 0xd9, 0xf7, 0xb0, 0x25, 0x83, 0x6c, 0xfe, 0xf5, 0x2c, 0x82,
0xfd, 0xdc, 0x57, 0x9e, 0x4c, 0x98, 0x6d, 0xf8, 0x88, 0xfd, 0x86, 0x7e, 0xa0, 0xb6, 0xc3, 0xc3, 0x2f, 0x92, 0x54, 0xb9, 0xd9, 0x54, 0xb5, 0x6a, 0x70, 0xfb, 0xb9, 0xae, 0x3c, 0x99, 0x30, 0xdb,
0xcf, 0x11, 0xfb, 0xdc, 0x19, 0x31, 0x6f, 0x6f, 0xe3, 0xed, 0x2f, 0x9b, 0x4b, 0xef, 0xe0, 0xef, 0xf0, 0x10, 0xfb, 0x0d, 0xfd, 0x40, 0x6d, 0x07, 0x97, 0x9f, 0x23, 0xf6, 0xb9, 0x33, 0x62, 0xd3,
0xed, 0xe9, 0x66, 0xec, 0x1d, 0xfc, 0xfd, 0x7c, 0xba, 0xb9, 0xf4, 0x1b, 0xfc, 0xbe, 0xfe, 0x75, 0xbd, 0x8d, 0x57, 0xbf, 0x6e, 0x2e, 0xbd, 0x86, 0xbf, 0x57, 0xef, 0x36, 0x63, 0xaf, 0xe1, 0xef,
0x33, 0xd6, 0x4f, 0x61, 0xef, 0x7a, 0xf0, 0x47, 0x00, 0x00, 0x00, 0xff, 0xff, 0x83, 0x88, 0xa1, 0x97, 0x77, 0x9b, 0x4b, 0xbf, 0xc3, 0xef, 0xcb, 0xdf, 0x36, 0x63, 0xfd, 0x14, 0xce, 0xae, 0x7b,
0x6a, 0xa6, 0x0d, 0x00, 0x00, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0x96, 0x0b, 0xf7, 0x15, 0xb6, 0x0d, 0x00, 0x00,
} }

View File

@ -63,7 +63,7 @@ message Folder {
} }
message Device { message Device {
bytes id = 1 [(gogoproto.customname) = "ID"]; bytes id = 1 [(gogoproto.customname) = "ID", (gogoproto.customtype) = "DeviceID", (gogoproto.nullable) = false];
string name = 2; string name = 2;
repeated string addresses = 3; repeated string addresses = 3;
Compression compression = 4; Compression compression = 4;

View File

@ -16,7 +16,9 @@ import (
"github.com/calmh/luhn" "github.com/calmh/luhn"
) )
type DeviceID [32]byte const DeviceIDLength = 32
type DeviceID [DeviceIDLength]byte
type ShortID uint64 type ShortID uint64
var LocalDeviceID = DeviceID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} var LocalDeviceID = DeviceID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
@ -114,6 +116,29 @@ func (n *DeviceID) UnmarshalText(bs []byte) error {
} }
} }
func (n *DeviceID) ProtoSize() int {
// Used by protobuf marshaller.
return DeviceIDLength
}
func (n *DeviceID) MarshalTo(bs []byte) (int, error) {
// Used by protobuf marshaller.
if len(bs) < DeviceIDLength {
return 0, errors.New("destination too short")
}
copy(bs, (*n)[:])
return DeviceIDLength, nil
}
func (n *DeviceID) Unmarshal(bs []byte) error {
// Used by protobuf marshaller.
if len(bs) < DeviceIDLength {
return errors.New("not enough data")
}
copy((*n)[:], bs)
return nil
}
func luhnify(s string) (string, error) { func luhnify(s string) (string, error) {
if len(s) != 52 { if len(s) != 52 {
panic("unsupported string length") panic("unsupported string length")

View File

@ -1,5 +1,8 @@
// Copyright (C) 2014 The Protocol Authors. // Copyright (C) 2014 The Protocol Authors.
//go:generate go run ../../script/protofmt.go deviceid_test.proto
//go:generate protoc --proto_path=../../../../../:../../../../gogo/protobuf/protobuf:. --gogofast_out=. deviceid_test.proto
package protocol package protocol
import "testing" import "testing"
@ -96,3 +99,53 @@ func TestDeviceIDFromBytes(t *testing.T) {
t.Errorf("Wrong device ID, got %q, want %q", id1, formatted) t.Errorf("Wrong device ID, got %q, want %q", id1, formatted)
} }
} }
func TestNewDeviceIDMarshalling(t *testing.T) {
// The new DeviceID.Unmarshal / DeviceID.MarshalTo serialization should
// be message compatible with how we used to serialize DeviceIDs.
// Create a message with a device ID in old style bytes format
id0, _ := DeviceIDFromString(formatted)
msg0 := TestOldDeviceID{id0[:]}
// Marshal it
bs, err := msg0.Marshal()
if err != nil {
t.Fatal(err)
}
// Unmarshal using the new DeviceID.Unmarshal
var msg1 TestNewDeviceID
if err := msg1.Unmarshal(bs); err != nil {
t.Fatal(err)
}
// Verify it's the same
if msg1.Test != id0 {
t.Error("Mismatch in old -> new direction")
}
// Marshal using the new DeviceID.MarshalTo
bs, err = msg1.Marshal()
if err != nil {
t.Fatal(err)
}
// Create an old style message and and attempt unmarshal
var msg2 TestOldDeviceID
if err := msg2.Unmarshal(bs); err != nil {
t.Fatal(err)
}
// Verify it's the same
if DeviceIDFromBytes(msg2.Test) != id0 {
t.Error("Mismatch in old -> new direction")
}
}

View File

@ -0,0 +1,442 @@
// Code generated by protoc-gen-gogo.
// source: deviceid_test.proto
// DO NOT EDIT!
/*
Package protocol is a generated protocol buffer package.
It is generated from these files:
deviceid_test.proto
It has these top-level messages:
TestOldDeviceID
TestNewDeviceID
*/
package protocol
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "github.com/gogo/protobuf/gogoproto"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
const _ = proto.GoGoProtoPackageIsVersion1
type TestOldDeviceID struct {
Test []byte `protobuf:"bytes,1,opt,name=test,proto3" json:"test,omitempty"`
}
func (m *TestOldDeviceID) Reset() { *m = TestOldDeviceID{} }
func (m *TestOldDeviceID) String() string { return proto.CompactTextString(m) }
func (*TestOldDeviceID) ProtoMessage() {}
func (*TestOldDeviceID) Descriptor() ([]byte, []int) { return fileDescriptorDeviceidTest, []int{0} }
type TestNewDeviceID struct {
Test DeviceID `protobuf:"bytes,1,opt,name=test,proto3,customtype=DeviceID" json:"test"`
}
func (m *TestNewDeviceID) Reset() { *m = TestNewDeviceID{} }
func (m *TestNewDeviceID) String() string { return proto.CompactTextString(m) }
func (*TestNewDeviceID) ProtoMessage() {}
func (*TestNewDeviceID) Descriptor() ([]byte, []int) { return fileDescriptorDeviceidTest, []int{1} }
func init() {
proto.RegisterType((*TestOldDeviceID)(nil), "protocol.TestOldDeviceID")
proto.RegisterType((*TestNewDeviceID)(nil), "protocol.TestNewDeviceID")
}
func (m *TestOldDeviceID) Marshal() (data []byte, err error) {
size := m.ProtoSize()
data = make([]byte, size)
n, err := m.MarshalTo(data)
if err != nil {
return nil, err
}
return data[:n], nil
}
func (m *TestOldDeviceID) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.Test) > 0 {
data[i] = 0xa
i++
i = encodeVarintDeviceidTest(data, i, uint64(len(m.Test)))
i += copy(data[i:], m.Test)
}
return i, nil
}
func (m *TestNewDeviceID) Marshal() (data []byte, err error) {
size := m.ProtoSize()
data = make([]byte, size)
n, err := m.MarshalTo(data)
if err != nil {
return nil, err
}
return data[:n], nil
}
func (m *TestNewDeviceID) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
data[i] = 0xa
i++
i = encodeVarintDeviceidTest(data, i, uint64(m.Test.ProtoSize()))
n1, err := m.Test.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n1
return i, nil
}
func encodeFixed64DeviceidTest(data []byte, offset int, v uint64) int {
data[offset] = uint8(v)
data[offset+1] = uint8(v >> 8)
data[offset+2] = uint8(v >> 16)
data[offset+3] = uint8(v >> 24)
data[offset+4] = uint8(v >> 32)
data[offset+5] = uint8(v >> 40)
data[offset+6] = uint8(v >> 48)
data[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32DeviceidTest(data []byte, offset int, v uint32) int {
data[offset] = uint8(v)
data[offset+1] = uint8(v >> 8)
data[offset+2] = uint8(v >> 16)
data[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintDeviceidTest(data []byte, offset int, v uint64) int {
for v >= 1<<7 {
data[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
data[offset] = uint8(v)
return offset + 1
}
func (m *TestOldDeviceID) ProtoSize() (n int) {
var l int
_ = l
l = len(m.Test)
if l > 0 {
n += 1 + l + sovDeviceidTest(uint64(l))
}
return n
}
func (m *TestNewDeviceID) ProtoSize() (n int) {
var l int
_ = l
l = m.Test.ProtoSize()
n += 1 + l + sovDeviceidTest(uint64(l))
return n
}
func sovDeviceidTest(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozDeviceidTest(x uint64) (n int) {
return sovDeviceidTest(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *TestOldDeviceID) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDeviceidTest
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: TestOldDeviceID: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TestOldDeviceID: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Test", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDeviceidTest
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
byteLen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthDeviceidTest
}
postIndex := iNdEx + byteLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Test = append(m.Test[:0], data[iNdEx:postIndex]...)
if m.Test == nil {
m.Test = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipDeviceidTest(data[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthDeviceidTest
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *TestNewDeviceID) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDeviceidTest
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: TestNewDeviceID: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TestNewDeviceID: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Test", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDeviceidTest
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
byteLen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthDeviceidTest
}
postIndex := iNdEx + byteLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.Test.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipDeviceidTest(data[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthDeviceidTest
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipDeviceidTest(data []byte) (n int, err error) {
l := len(data)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowDeviceidTest
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowDeviceidTest
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if data[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowDeviceidTest
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthDeviceidTest
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowDeviceidTest
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipDeviceidTest(data[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthDeviceidTest = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowDeviceidTest = fmt.Errorf("proto: integer overflow")
)
var fileDescriptorDeviceidTest = []byte{
// 171 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x12, 0x4e, 0x49, 0x2d, 0xcb,
0x4c, 0x4e, 0xcd, 0x4c, 0x89, 0x2f, 0x49, 0x2d, 0x2e, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17,
0xe2, 0x00, 0x53, 0xc9, 0xf9, 0x39, 0x52, 0xba, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9,
0xf9, 0xb9, 0xfa, 0xe9, 0xf9, 0xe9, 0xf9, 0xfa, 0x60, 0x99, 0xa4, 0xd2, 0x34, 0x30, 0x0f, 0xcc,
0x01, 0xb3, 0x20, 0x1a, 0x95, 0x54, 0xb9, 0xf8, 0x43, 0x80, 0xc6, 0xf8, 0xe7, 0xa4, 0xb8, 0x80,
0x8d, 0xf5, 0x74, 0x11, 0x12, 0xe2, 0x62, 0x01, 0x99, 0x2c, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x13,
0x04, 0x66, 0x2b, 0x99, 0x43, 0x94, 0xf9, 0xa5, 0x96, 0xc3, 0x95, 0xa9, 0x20, 0x2b, 0x73, 0x12,
0x38, 0x71, 0x4f, 0x9e, 0xe1, 0xd6, 0x3d, 0x79, 0x0e, 0x98, 0x3c, 0x44, 0xa3, 0x93, 0xcc, 0x89,
0x87, 0x72, 0x0c, 0x17, 0x80, 0xf8, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x40, 0xfc, 0xe0, 0x91, 0x1c,
0xc3, 0x0b, 0x20, 0x5e, 0xf0, 0x58, 0x8e, 0x31, 0x89, 0x0d, 0xec, 0x08, 0x63, 0x40, 0x00, 0x00,
0x00, 0xff, 0xff, 0x35, 0x9c, 0x00, 0x78, 0xd4, 0x00, 0x00, 0x00,
}

View File

@ -0,0 +1,20 @@
syntax = "proto3";
package protocol;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
option (gogoproto.goproto_getters_all) = false;
option (gogoproto.sizer_all) = false;
option (gogoproto.protosizer_all) = true;
option (gogoproto.goproto_enum_stringer_all) = false;
option (gogoproto.goproto_enum_prefix_all) = false;
message TestOldDeviceID {
bytes test = 1;
}
message TestNewDeviceID {
bytes test = 1 [(gogoproto.customtype) = "DeviceID", (gogoproto.nullable) = false];
}