mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-22 10:58:57 +00:00
wip
This commit is contained in:
parent
da9726ddca
commit
f19a9c49af
@ -44,6 +44,7 @@ type DeviceConfiguration struct {
|
||||
MaxRequestKiB int `protobuf:"varint,16,opt,name=max_request_kib,json=maxRequestKib,proto3,casttype=int" json:"maxRequestKiB" xml:"maxRequestKiB"`
|
||||
Untrusted bool `protobuf:"varint,17,opt,name=untrusted,proto3" json:"untrusted" xml:"untrusted"`
|
||||
RemoteGUIPort int `protobuf:"varint,18,opt,name=remote_gui_port,json=remoteGuiPort,proto3,casttype=int" json:"remoteGUIPort" xml:"remoteGUIPort"`
|
||||
MultipleConnections int `protobuf:"varint,19,opt,name=multiple_connections,json=multipleConnections,proto3,casttype=int" json:"multipleConnections" xml:"multipleConnections"`
|
||||
}
|
||||
|
||||
func (m *DeviceConfiguration) Reset() { *m = DeviceConfiguration{} }
|
||||
@ -88,72 +89,74 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_744b782bd13071dd = []byte{
|
||||
// 1026 bytes of a gzipped FileDescriptorProto
|
||||
// 1064 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0xbf, 0x6f, 0xdb, 0x46,
|
||||
0x18, 0x15, 0xeb, 0xc4, 0xb6, 0xce, 0x3f, 0x64, 0xd3, 0x88, 0xc3, 0x18, 0x88, 0x4e, 0x50, 0x35,
|
||||
0x28, 0x68, 0x22, 0x17, 0x6e, 0x27, 0xa3, 0x2d, 0x50, 0xc6, 0x68, 0x63, 0x18, 0x4d, 0x5c, 0x16,
|
||||
0x5d, 0xbc, 0xb0, 0x24, 0xef, 0xac, 0x1c, 0x2c, 0xf2, 0x58, 0xf2, 0xa8, 0x58, 0x40, 0xff, 0x80,
|
||||
0x76, 0x2b, 0x02, 0x74, 0xea, 0x92, 0xf6, 0xdf, 0xe8, 0xd0, 0xd5, 0x9b, 0x35, 0x16, 0x1d, 0x0e,
|
||||
0x88, 0xbd, 0x71, 0x29, 0xc0, 0x31, 0x53, 0x71, 0x77, 0x14, 0x45, 0xca, 0x51, 0x50, 0xa0, 0x1b,
|
||||
0xef, 0xbd, 0x77, 0xef, 0xdd, 0xf7, 0xe9, 0xbb, 0x13, 0xe8, 0x0c, 0x88, 0xbb, 0xeb, 0xd1, 0xe0,
|
||||
0x94, 0xf4, 0x77, 0x11, 0x1e, 0x12, 0x0f, 0xab, 0x45, 0x12, 0x39, 0x8c, 0xd0, 0xa0, 0x17, 0x46,
|
||||
0x94, 0x51, 0x7d, 0x51, 0x81, 0x3b, 0xdb, 0x42, 0x2d, 0x21, 0x8f, 0x0e, 0x76, 0x5d, 0x1c, 0x2a,
|
||||
0x7e, 0xe7, 0x5e, 0xc9, 0x85, 0xba, 0x31, 0x8e, 0x86, 0x18, 0xe5, 0x54, 0x1d, 0x9f, 0x33, 0xf5,
|
||||
0xd9, 0xfe, 0x67, 0x03, 0x6c, 0x1d, 0xc8, 0x8c, 0xc7, 0xe5, 0x0c, 0xfd, 0x4f, 0x0d, 0xd4, 0x55,
|
||||
0xb6, 0x4d, 0x90, 0xa1, 0xb5, 0xb4, 0xee, 0xaa, 0xf9, 0x9b, 0x76, 0xc1, 0x61, 0xed, 0x6f, 0x0e,
|
||||
0x3f, 0xee, 0x13, 0xf6, 0x3c, 0x71, 0x7b, 0x1e, 0xf5, 0x77, 0xe3, 0x51, 0xe0, 0xb1, 0xe7, 0x24,
|
||||
0xe8, 0x97, 0xbe, 0xca, 0x27, 0xea, 0x29, 0xf7, 0xc3, 0x83, 0x2b, 0x0e, 0x97, 0x27, 0xdf, 0x29,
|
||||
0x87, 0xcb, 0x28, 0xff, 0xce, 0x38, 0x6c, 0x9e, 0xfb, 0x83, 0xfd, 0x36, 0x41, 0x0f, 0x1d, 0xc6,
|
||||
0xa2, 0x76, 0x2b, 0xa0, 0x08, 0x9f, 0x3a, 0xc9, 0x80, 0xed, 0xb7, 0x59, 0x94, 0xe0, 0x76, 0x7a,
|
||||
0xd9, 0x59, 0xca, 0xc9, 0xec, 0xb2, 0x53, 0x6c, 0xfc, 0x71, 0xdc, 0xd1, 0x5e, 0x8e, 0x3b, 0x85,
|
||||
0xe9, 0xab, 0x71, 0x47, 0xb3, 0x26, 0x2c, 0xd2, 0x8f, 0xc1, 0xad, 0xc0, 0xf1, 0xb1, 0xf1, 0x5e,
|
||||
0x4b, 0xeb, 0xd6, 0xcd, 0x4f, 0x52, 0x0e, 0xe5, 0x3a, 0xe3, 0xf0, 0x9e, 0x8c, 0x13, 0x0b, 0xe9,
|
||||
0xf9, 0x90, 0xfa, 0x84, 0x61, 0x3f, 0x64, 0x23, 0x91, 0xb4, 0xf5, 0x16, 0xdc, 0x92, 0x3b, 0xf5,
|
||||
0x73, 0x50, 0x77, 0x10, 0x8a, 0x70, 0x1c, 0xe3, 0xd8, 0x58, 0x68, 0x2d, 0x74, 0xeb, 0xe6, 0x49,
|
||||
0xca, 0xe1, 0x14, 0xcc, 0x38, 0x7c, 0x20, 0xbd, 0x73, 0xa4, 0xe4, 0xdc, 0x2a, 0x4a, 0x42, 0xa3,
|
||||
0xc0, 0xf1, 0x89, 0x27, 0xb2, 0x36, 0x6f, 0xe8, 0xde, 0x5c, 0x76, 0x96, 0x72, 0x81, 0x35, 0xf5,
|
||||
0xd5, 0x87, 0x60, 0xc5, 0xa3, 0x7e, 0x28, 0x56, 0x84, 0x06, 0xc6, 0xad, 0x96, 0xd6, 0x5d, 0xdf,
|
||||
0xbb, 0xd3, 0x2b, 0x7a, 0xfc, 0x78, 0x4a, 0x9a, 0x9f, 0xa6, 0x1c, 0x96, 0xd5, 0x19, 0x87, 0xdb,
|
||||
0xf2, 0x50, 0x25, 0x4c, 0x35, 0x3a, 0xbd, 0xec, 0x6c, 0xcc, 0x82, 0x56, 0x79, 0xab, 0x8e, 0x41,
|
||||
0xdd, 0xc3, 0x11, 0xb3, 0x65, 0x23, 0x6f, 0xcb, 0x46, 0x3e, 0x11, 0xbf, 0x9d, 0x00, 0x9f, 0xaa,
|
||||
0x66, 0xde, 0x57, 0xde, 0x39, 0xf0, 0x96, 0x86, 0xde, 0x9d, 0xc3, 0x59, 0x85, 0x8b, 0x7e, 0x02,
|
||||
0x00, 0x09, 0x58, 0x44, 0x51, 0xe2, 0xe1, 0xc8, 0x58, 0x6c, 0x69, 0xdd, 0x65, 0x73, 0x3f, 0xe5,
|
||||
0xb0, 0x84, 0x66, 0x1c, 0xde, 0x51, 0x53, 0x52, 0x40, 0x45, 0x11, 0x8d, 0x19, 0xcc, 0x2a, 0xed,
|
||||
0xd3, 0x7f, 0xd7, 0xc0, 0x4e, 0x7c, 0x46, 0x42, 0x7b, 0x82, 0x89, 0xf1, 0xb6, 0x23, 0xec, 0xd3,
|
||||
0xa1, 0x33, 0x88, 0x8d, 0x25, 0x19, 0x86, 0x52, 0x0e, 0x0d, 0xa1, 0x3a, 0x2c, 0x89, 0xac, 0x5c,
|
||||
0x93, 0x71, 0xf8, 0xbe, 0x8c, 0x9e, 0x27, 0x28, 0x0e, 0x72, 0xff, 0x9d, 0x0a, 0x6b, 0x6e, 0x82,
|
||||
0xfe, 0x87, 0x06, 0xd6, 0x8a, 0x33, 0x23, 0xdb, 0x1d, 0x19, 0xcb, 0xf2, 0xc6, 0xfd, 0xf2, 0xbf,
|
||||
0x6e, 0x5c, 0xca, 0xe1, 0xea, 0xd4, 0xd5, 0x1c, 0x65, 0x1c, 0x76, 0xab, 0x3d, 0x44, 0xe6, 0x68,
|
||||
0xfe, 0x9d, 0xdb, 0xbc, 0x21, 0x13, 0x37, 0x4e, 0xde, 0xb2, 0x8a, 0xad, 0xbe, 0x07, 0x16, 0x43,
|
||||
0x27, 0x89, 0x31, 0x32, 0xea, 0xb2, 0x9b, 0x3b, 0x29, 0x87, 0x39, 0x92, 0x71, 0xb8, 0x2a, 0x23,
|
||||
0xd5, 0xb2, 0x6d, 0xe5, 0xb8, 0xfe, 0x03, 0xd8, 0x70, 0x06, 0x03, 0xfa, 0x02, 0x23, 0x3b, 0xc0,
|
||||
0xec, 0x05, 0x8d, 0xce, 0x62, 0x03, 0xc8, 0x2b, 0xf5, 0x75, 0xca, 0x61, 0x23, 0xe7, 0x9e, 0xe6,
|
||||
0x54, 0xf1, 0x46, 0x54, 0xf1, 0xea, 0xa0, 0x19, 0xf3, 0x48, 0x6b, 0xd6, 0x4e, 0xff, 0x0e, 0x6c,
|
||||
0x39, 0x09, 0xa3, 0xb6, 0xe3, 0x79, 0x38, 0x64, 0xf6, 0x29, 0x1d, 0x20, 0x1c, 0xc5, 0xc6, 0x8a,
|
||||
0x3c, 0xfe, 0x87, 0x29, 0x87, 0x9b, 0x82, 0xfe, 0x5c, 0xb2, 0x5f, 0x28, 0x32, 0xe3, 0xf0, 0xae,
|
||||
0x3a, 0xc2, 0x2c, 0xd3, 0xb6, 0x6e, 0xaa, 0xf5, 0x67, 0x60, 0xcd, 0x77, 0xce, 0xed, 0x18, 0x07,
|
||||
0xc8, 0x3e, 0x73, 0xc3, 0xd8, 0x58, 0x6d, 0x69, 0xdd, 0xdb, 0xe6, 0x07, 0xe2, 0x72, 0xfa, 0xce,
|
||||
0xf9, 0x37, 0x38, 0x40, 0x47, 0x6e, 0x28, 0x5c, 0x37, 0xa5, 0x6b, 0x09, 0x6b, 0xbf, 0xe1, 0x70,
|
||||
0x81, 0x04, 0xcc, 0x2a, 0x0b, 0x27, 0x86, 0x11, 0xf6, 0x86, 0xca, 0x70, 0xad, 0x62, 0x68, 0x61,
|
||||
0x6f, 0x38, 0x6b, 0x38, 0xc1, 0x2a, 0x86, 0x13, 0x50, 0x0f, 0x40, 0x83, 0xf4, 0x03, 0x1a, 0x61,
|
||||
0x54, 0xd4, 0xbf, 0xde, 0x5a, 0xe8, 0xae, 0xec, 0x6d, 0xf7, 0xd4, 0xbf, 0x46, 0xef, 0x59, 0xfe,
|
||||
0xaf, 0xa1, 0x6a, 0x32, 0x1f, 0x89, 0x59, 0x4c, 0x39, 0x5c, 0xcf, 0xb7, 0x4d, 0x1b, 0xb3, 0xa5,
|
||||
0xa6, 0xaa, 0x0c, 0xb7, 0xad, 0x19, 0x99, 0xfe, 0x93, 0x06, 0x1a, 0x21, 0x0e, 0x10, 0x09, 0xfa,
|
||||
0x45, 0x60, 0xe3, 0x9d, 0x81, 0x4f, 0x44, 0xe0, 0x15, 0x87, 0xc6, 0x01, 0x0e, 0x23, 0xec, 0x39,
|
||||
0x0c, 0xa3, 0x63, 0x65, 0x90, 0x7b, 0xa6, 0x1c, 0x6a, 0x8f, 0x8a, 0x37, 0x28, 0x2c, 0x73, 0xa5,
|
||||
0xd1, 0x30, 0x34, 0x6b, 0xbd, 0xc2, 0xc5, 0xfa, 0xaf, 0x1a, 0x68, 0xa8, 0x6e, 0x7e, 0x9f, 0xe0,
|
||||
0x98, 0xd9, 0x67, 0xc4, 0x35, 0x36, 0x64, 0x3f, 0xe3, 0x2b, 0x0e, 0xd7, 0xbe, 0x12, 0x6d, 0x92,
|
||||
0xcc, 0x11, 0x31, 0x53, 0x0e, 0xd7, 0xfc, 0x32, 0x50, 0x14, 0x5c, 0x41, 0x27, 0x4d, 0x4e, 0x2f,
|
||||
0x3b, 0x33, 0xf2, 0x59, 0xe0, 0xe5, 0xb8, 0x53, 0x4d, 0xb0, 0x2a, 0xbc, 0xab, 0x7f, 0x06, 0xea,
|
||||
0x49, 0xc0, 0xa2, 0x24, 0x66, 0x18, 0x19, 0x9b, 0x72, 0x26, 0x5b, 0xe2, 0x7f, 0xa6, 0x00, 0x33,
|
||||
0x0e, 0x1b, 0xf2, 0x04, 0x05, 0xd2, 0xb6, 0xa6, 0xac, 0xac, 0x4e, 0x3c, 0x70, 0x0c, 0xdb, 0xfd,
|
||||
0x84, 0xd8, 0x21, 0x8d, 0x98, 0xa1, 0x4f, 0xab, 0xb3, 0x24, 0xf5, 0xe5, 0xb7, 0x87, 0xc7, 0x34,
|
||||
0x62, 0xa2, 0xba, 0xa8, 0x0c, 0x14, 0xd5, 0x55, 0xd0, 0x72, 0x75, 0x55, 0xf9, 0x2c, 0x20, 0xaa,
|
||||
0xab, 0x24, 0x58, 0x13, 0x3e, 0x21, 0x62, 0x69, 0x1e, 0x5d, 0xbc, 0x6e, 0xd6, 0xc6, 0xaf, 0x9b,
|
||||
0xb5, 0x8b, 0xab, 0xa6, 0x36, 0xbe, 0x6a, 0x6a, 0x3f, 0x5f, 0x37, 0x6b, 0xaf, 0xae, 0x9b, 0xda,
|
||||
0xf8, 0xba, 0x59, 0xfb, 0xeb, 0xba, 0x59, 0x3b, 0x79, 0xf0, 0x1f, 0x1e, 0x3b, 0x35, 0x31, 0xee,
|
||||
0xa2, 0x7c, 0xf4, 0x3e, 0xfa, 0x37, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x4a, 0x4f, 0x60, 0x33, 0x09,
|
||||
0x00, 0x00,
|
||||
0x14, 0x16, 0xeb, 0xc4, 0xb1, 0xce, 0x3f, 0x64, 0x51, 0x8d, 0xc3, 0x18, 0x88, 0x4e, 0x50, 0x35,
|
||||
0x28, 0x68, 0x22, 0x17, 0x6e, 0x27, 0xf7, 0x07, 0x50, 0xda, 0x68, 0x63, 0x18, 0x4d, 0x5c, 0x16,
|
||||
0x5d, 0xbc, 0xb0, 0x14, 0xef, 0xac, 0x1c, 0x2c, 0xde, 0xb1, 0xe4, 0x51, 0xb1, 0x80, 0xfe, 0x01,
|
||||
0xed, 0x56, 0x04, 0xe8, 0xd4, 0x25, 0xed, 0xbf, 0xd1, 0xa1, 0xab, 0x37, 0x6b, 0x2c, 0x3a, 0x5c,
|
||||
0x11, 0x7b, 0xe3, 0xc8, 0x31, 0x53, 0x71, 0x47, 0x8a, 0x22, 0x65, 0x3b, 0x28, 0xd0, 0x8d, 0xf7,
|
||||
0x7d, 0xef, 0xbe, 0xef, 0xbd, 0xc7, 0x77, 0x77, 0xa0, 0x33, 0x24, 0xfd, 0x2d, 0x97, 0xd1, 0x63,
|
||||
0x32, 0xd8, 0x42, 0x78, 0x44, 0x5c, 0x9c, 0x2e, 0xa2, 0xc0, 0xe1, 0x84, 0xd1, 0x9e, 0x1f, 0x30,
|
||||
0xce, 0xf4, 0xc5, 0x14, 0xdc, 0xdc, 0x90, 0xd1, 0x0a, 0x72, 0xd9, 0x70, 0xab, 0x8f, 0xfd, 0x94,
|
||||
0xdf, 0xbc, 0x5f, 0x50, 0x61, 0xfd, 0x10, 0x07, 0x23, 0x8c, 0x32, 0xaa, 0x8a, 0x4f, 0x79, 0xfa,
|
||||
0xd9, 0xfe, 0xa7, 0x0e, 0x1a, 0x7b, 0xca, 0x63, 0xb7, 0xe8, 0xa1, 0xff, 0xa9, 0x81, 0x6a, 0xea,
|
||||
0x6d, 0x13, 0x64, 0x68, 0x2d, 0xad, 0xbb, 0x62, 0xfe, 0xa6, 0x9d, 0x09, 0x58, 0xf9, 0x5b, 0xc0,
|
||||
0x8f, 0x06, 0x84, 0x3f, 0x8f, 0xfa, 0x3d, 0x97, 0x79, 0x5b, 0xe1, 0x98, 0xba, 0xfc, 0x39, 0xa1,
|
||||
0x83, 0xc2, 0x57, 0x31, 0xa3, 0x5e, 0xaa, 0xbe, 0xbf, 0x77, 0x21, 0xe0, 0xd2, 0xf4, 0x3b, 0x16,
|
||||
0x70, 0x09, 0x65, 0xdf, 0x89, 0x80, 0xcd, 0x53, 0x6f, 0xb8, 0xd3, 0x26, 0xe8, 0x91, 0xc3, 0x79,
|
||||
0xd0, 0x6e, 0x51, 0x86, 0xf0, 0xb1, 0x13, 0x0d, 0xf9, 0x4e, 0x9b, 0x07, 0x11, 0x6e, 0xc7, 0xe7,
|
||||
0x9d, 0x3b, 0x19, 0x99, 0x9c, 0x77, 0xf2, 0x8d, 0x3f, 0x4e, 0x3a, 0xda, 0xcb, 0x49, 0x27, 0x17,
|
||||
0x7d, 0x35, 0xe9, 0x68, 0xd6, 0x94, 0x45, 0xfa, 0x21, 0xb8, 0x45, 0x1d, 0x0f, 0x1b, 0xef, 0xb4,
|
||||
0xb4, 0x6e, 0xd5, 0xfc, 0x24, 0x16, 0x50, 0xad, 0x13, 0x01, 0xef, 0x2b, 0x3b, 0xb9, 0x50, 0x9a,
|
||||
0x8f, 0x98, 0x47, 0x38, 0xf6, 0x7c, 0x3e, 0x96, 0x4e, 0x8d, 0x6b, 0x70, 0x4b, 0xed, 0xd4, 0x4f,
|
||||
0x41, 0xd5, 0x41, 0x28, 0xc0, 0x61, 0x88, 0x43, 0x63, 0xa1, 0xb5, 0xd0, 0xad, 0x9a, 0x47, 0xb1,
|
||||
0x80, 0x33, 0x30, 0x11, 0xf0, 0xa1, 0xd2, 0xce, 0x90, 0x82, 0x72, 0x2b, 0x2f, 0x09, 0x8d, 0xa9,
|
||||
0xe3, 0x11, 0x57, 0x7a, 0xd5, 0xaf, 0xc4, 0xbd, 0x39, 0xef, 0xdc, 0xc9, 0x02, 0xac, 0x99, 0xae,
|
||||
0x3e, 0x02, 0xcb, 0x2e, 0xf3, 0x7c, 0xb9, 0x22, 0x8c, 0x1a, 0xb7, 0x5a, 0x5a, 0x77, 0x6d, 0xfb,
|
||||
0x6e, 0x2f, 0xef, 0xf1, 0xee, 0x8c, 0x34, 0x3f, 0x8d, 0x05, 0x2c, 0x46, 0x27, 0x02, 0x6e, 0xa8,
|
||||
0xa4, 0x0a, 0x58, 0xda, 0xe8, 0xf8, 0xbc, 0xb3, 0x3e, 0x0f, 0x5a, 0xc5, 0xad, 0x3a, 0x06, 0x55,
|
||||
0x17, 0x07, 0xdc, 0x56, 0x8d, 0xbc, 0xad, 0x1a, 0xf9, 0x44, 0xfe, 0x3b, 0x09, 0x3e, 0x4d, 0x9b,
|
||||
0xf9, 0x20, 0xd5, 0xce, 0x80, 0x6b, 0x1a, 0x7a, 0xef, 0x06, 0xce, 0xca, 0x55, 0xf4, 0x23, 0x00,
|
||||
0x08, 0xe5, 0x01, 0x43, 0x91, 0x8b, 0x03, 0x63, 0xb1, 0xa5, 0x75, 0x97, 0xcc, 0x9d, 0x58, 0xc0,
|
||||
0x02, 0x9a, 0x08, 0x78, 0x37, 0x9d, 0x92, 0x1c, 0xca, 0x8b, 0xa8, 0xcd, 0x61, 0x56, 0x61, 0x9f,
|
||||
0xfe, 0xbb, 0x06, 0x36, 0xc3, 0x13, 0xe2, 0xdb, 0x53, 0x4c, 0x8e, 0xb7, 0x1d, 0x60, 0x8f, 0x8d,
|
||||
0x9c, 0x61, 0x68, 0xdc, 0x51, 0x66, 0x28, 0x16, 0xd0, 0x90, 0x51, 0xfb, 0x85, 0x20, 0x2b, 0x8b,
|
||||
0x49, 0x04, 0x7c, 0x4f, 0x59, 0xdf, 0x14, 0x90, 0x27, 0xf2, 0xe0, 0xad, 0x11, 0xd6, 0x8d, 0x0e,
|
||||
0xfa, 0x1f, 0x1a, 0x58, 0xcd, 0x73, 0x46, 0x76, 0x7f, 0x6c, 0x2c, 0xa9, 0x13, 0xf7, 0xcb, 0xff,
|
||||
0x3a, 0x71, 0xb1, 0x80, 0x2b, 0x33, 0x55, 0x73, 0x9c, 0x08, 0xd8, 0x2d, 0xf7, 0x10, 0x99, 0xe3,
|
||||
0x9b, 0xcf, 0x5c, 0xfd, 0x4a, 0x98, 0x3c, 0x71, 0xea, 0x94, 0x95, 0x64, 0xf5, 0x6d, 0xb0, 0xe8,
|
||||
0x3b, 0x51, 0x88, 0x91, 0x51, 0x55, 0xdd, 0xdc, 0x8c, 0x05, 0xcc, 0x90, 0x44, 0xc0, 0x15, 0x65,
|
||||
0x99, 0x2e, 0xdb, 0x56, 0x86, 0xeb, 0x3f, 0x80, 0x75, 0x67, 0x38, 0x64, 0x2f, 0x30, 0xb2, 0x29,
|
||||
0xe6, 0x2f, 0x58, 0x70, 0x12, 0x1a, 0x40, 0x1d, 0xa9, 0xaf, 0x63, 0x01, 0x6b, 0x19, 0xf7, 0x34,
|
||||
0xa3, 0xf2, 0x3b, 0xa2, 0x8c, 0x97, 0x07, 0xcd, 0xb8, 0x89, 0xb4, 0xe6, 0xe5, 0xf4, 0xef, 0x40,
|
||||
0xc3, 0x89, 0x38, 0xb3, 0x1d, 0xd7, 0xc5, 0x3e, 0xb7, 0x8f, 0xd9, 0x10, 0xe1, 0x20, 0x34, 0x96,
|
||||
0x55, 0xfa, 0x1f, 0xc4, 0x02, 0xd6, 0x25, 0xfd, 0xb9, 0x62, 0xbf, 0x48, 0xc9, 0x44, 0xc0, 0x7b,
|
||||
0x69, 0x0a, 0xf3, 0x4c, 0xdb, 0xba, 0x1a, 0xad, 0x3f, 0x03, 0xab, 0x9e, 0x73, 0x6a, 0x87, 0x98,
|
||||
0x22, 0xfb, 0xa4, 0xef, 0x87, 0xc6, 0x4a, 0x4b, 0xeb, 0xde, 0x36, 0xdf, 0x97, 0x87, 0xd3, 0x73,
|
||||
0x4e, 0xbf, 0xc1, 0x14, 0x1d, 0xf4, 0x7d, 0xa9, 0x5a, 0x57, 0xaa, 0x05, 0xac, 0xfd, 0x46, 0xc0,
|
||||
0x05, 0x42, 0xb9, 0x55, 0x0c, 0x9c, 0x0a, 0x06, 0xd8, 0x1d, 0xa5, 0x82, 0xab, 0x25, 0x41, 0x0b,
|
||||
0xbb, 0xa3, 0x79, 0xc1, 0x29, 0x56, 0x12, 0x9c, 0x82, 0x3a, 0x05, 0x35, 0x32, 0xa0, 0x2c, 0xc0,
|
||||
0x28, 0xaf, 0x7f, 0xad, 0xb5, 0xd0, 0x5d, 0xde, 0xde, 0xe8, 0xa5, 0xaf, 0x46, 0xef, 0x59, 0xf6,
|
||||
0x6a, 0xa4, 0x35, 0x99, 0x8f, 0xe5, 0x2c, 0xc6, 0x02, 0xae, 0x65, 0xdb, 0x66, 0x8d, 0x69, 0xa4,
|
||||
0x53, 0x55, 0x84, 0xdb, 0xd6, 0x5c, 0x98, 0xfe, 0x93, 0x06, 0x6a, 0x3e, 0xa6, 0x88, 0xd0, 0x41,
|
||||
0x6e, 0x58, 0x7b, 0xab, 0xe1, 0x13, 0x69, 0x78, 0x21, 0xa0, 0xb1, 0x87, 0xfd, 0x00, 0xbb, 0x0e,
|
||||
0xc7, 0xe8, 0x30, 0x15, 0xc8, 0x34, 0x63, 0x01, 0xb5, 0xc7, 0xf9, 0x1d, 0xe4, 0x17, 0xb9, 0xc2,
|
||||
0x68, 0x18, 0x9a, 0xb5, 0x56, 0xe2, 0x42, 0xfd, 0x57, 0x0d, 0xd4, 0xd2, 0x6e, 0x7e, 0x1f, 0xe1,
|
||||
0x90, 0xdb, 0x27, 0xa4, 0x6f, 0xac, 0xab, 0x7e, 0x86, 0x17, 0x02, 0xae, 0x7e, 0x25, 0xdb, 0xa4,
|
||||
0x98, 0x03, 0x62, 0xc6, 0x02, 0xae, 0x7a, 0x45, 0x20, 0x2f, 0xb8, 0x84, 0x4e, 0x9b, 0x1c, 0x9f,
|
||||
0x77, 0xe6, 0xc2, 0xe7, 0x81, 0x97, 0x93, 0x4e, 0xd9, 0xc1, 0x2a, 0xf1, 0x7d, 0xfd, 0x33, 0x50,
|
||||
0x8d, 0x28, 0x0f, 0xa2, 0x90, 0x63, 0x64, 0xd4, 0xd5, 0x4c, 0xb6, 0xe4, 0x3b, 0x93, 0x83, 0x89,
|
||||
0x80, 0x35, 0x95, 0x41, 0x8e, 0xb4, 0xad, 0x19, 0xab, 0xaa, 0x93, 0x17, 0x1c, 0xc7, 0xf6, 0x20,
|
||||
0x22, 0xb6, 0xcf, 0x02, 0x6e, 0xe8, 0xb3, 0xea, 0x2c, 0x45, 0x7d, 0xf9, 0xed, 0xfe, 0x21, 0x0b,
|
||||
0xb8, 0xac, 0x2e, 0x28, 0x02, 0x79, 0x75, 0x25, 0xb4, 0x58, 0x5d, 0x39, 0x7c, 0x1e, 0x90, 0xd5,
|
||||
0x95, 0x1c, 0xac, 0x29, 0x1f, 0x11, 0xb9, 0xd4, 0x29, 0x78, 0xd7, 0x8b, 0x86, 0x9c, 0xf8, 0x43,
|
||||
0x6c, 0xbb, 0x8c, 0x52, 0xac, 0xae, 0xc2, 0xd0, 0x68, 0xa8, 0x0c, 0x3f, 0x8e, 0x05, 0x6c, 0x4c,
|
||||
0xf9, 0xdd, 0x19, 0x9d, 0x3f, 0xdb, 0xd7, 0x70, 0xf9, 0x7c, 0x5f, 0xb7, 0xd1, 0x3c, 0x38, 0x7b,
|
||||
0xdd, 0xac, 0x4c, 0x5e, 0x37, 0x2b, 0x67, 0x17, 0x4d, 0x6d, 0x72, 0xd1, 0xd4, 0x7e, 0xbe, 0x6c,
|
||||
0x56, 0x5e, 0x5d, 0x36, 0xb5, 0xc9, 0x65, 0xb3, 0xf2, 0xd7, 0x65, 0xb3, 0x72, 0xf4, 0xf0, 0x3f,
|
||||
0x5c, 0xae, 0xe9, 0x84, 0xf6, 0x17, 0xd5, 0x25, 0xfb, 0xe1, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff,
|
||||
0xd1, 0x8c, 0x1d, 0x62, 0xa3, 0x09, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *DeviceConfiguration) Marshal() (dAtA []byte, err error) {
|
||||
@ -176,6 +179,13 @@ func (m *DeviceConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.MultipleConnections != 0 {
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(m.MultipleConnections))
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0x98
|
||||
}
|
||||
if m.RemoteGUIPort != 0 {
|
||||
i = encodeVarintDeviceconfiguration(dAtA, i, uint64(m.RemoteGUIPort))
|
||||
i--
|
||||
@ -423,6 +433,9 @@ func (m *DeviceConfiguration) ProtoSize() (n int) {
|
||||
if m.RemoteGUIPort != 0 {
|
||||
n += 2 + sovDeviceconfiguration(uint64(m.RemoteGUIPort))
|
||||
}
|
||||
if m.MultipleConnections != 0 {
|
||||
n += 2 + sovDeviceconfiguration(uint64(m.MultipleConnections))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@ -918,6 +931,25 @@ func (m *DeviceConfiguration) Unmarshal(dAtA []byte) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 19:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field MultipleConnections", wireType)
|
||||
}
|
||||
m.MultipleConnections = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDeviceconfiguration
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.MultipleConnections |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipDeviceconfiguration(dAtA[iNdEx:])
|
||||
|
@ -171,6 +171,9 @@ type service struct {
|
||||
listenersMut sync.RWMutex
|
||||
listeners map[string]genericListener
|
||||
listenerTokens map[string]suture.ServiceToken
|
||||
|
||||
connectionsMut sync.Mutex
|
||||
connections map[protocol.DeviceID]int
|
||||
}
|
||||
|
||||
func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, bepProtocolName string, tlsDefaultCommonName string, evLogger events.Logger, registry *registry.Registry, keyGen *protocol.KeyGenerator) Service {
|
||||
@ -202,6 +205,9 @@ func NewService(cfg config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *t
|
||||
listenersMut: sync.NewRWMutex(),
|
||||
listeners: make(map[string]genericListener),
|
||||
listenerTokens: make(map[string]suture.ServiceToken),
|
||||
|
||||
connectionsMut: sync.NewMutex(),
|
||||
connections: make(map[protocol.DeviceID]int),
|
||||
}
|
||||
cfg.Subscribe(service)
|
||||
|
||||
@ -316,7 +322,7 @@ func (s *service) connectionCheckEarly(remoteID protocol.DeviceID, c internalCon
|
||||
if ct, ok := s.model.Connection(remoteID); ok {
|
||||
if ct.Priority() > c.priority || time.Since(ct.Statistics().StartedAt) > minConnectionReplaceAge {
|
||||
l.Debugf("Switching connections %s (existing: %s new: %s)", remoteID, ct, c)
|
||||
} else {
|
||||
} else if cfg.MultipleConnections <= s.connectionsForDevice(cfg.DeviceID) {
|
||||
// We should not already be connected to the other party. TODO: This
|
||||
// could use some better handling. If the old connection is dead but
|
||||
// hasn't timed out yet we may want to drop *that* connection and keep
|
||||
@ -412,9 +418,16 @@ func (s *service) handleHellos(ctx context.Context) error {
|
||||
// connections are limited.
|
||||
rd, wr := s.limiter.getLimiters(remoteID, c, c.IsLocal())
|
||||
|
||||
// Amazing hack: We need to pass the connection to the model, but we
|
||||
// also need to pass the model to the connection. The
|
||||
// connectionContextModel handles the mediation by being constructed
|
||||
// in two stages...
|
||||
protoConn := protocol.NewConnection(remoteID, rd, wr, c, s.model, c, deviceCfg.Compression, s.cfg.FolderPasswords(remoteID), s.keyGen)
|
||||
|
||||
s.accountAddedConnection(remoteID)
|
||||
go func() {
|
||||
<-protoConn.Closed()
|
||||
s.accountRemovedConnection(remoteID)
|
||||
s.dialNowDevicesMut.Lock()
|
||||
s.dialNowDevices[remoteID] = struct{}{}
|
||||
s.scheduleDialNow()
|
||||
@ -552,9 +565,10 @@ func (s *service) dialDevices(ctx context.Context, now time.Time, cfg config.Con
|
||||
// we don't attempt dialers that aren't considered a worthy upgrade.
|
||||
priorityCutoff -= cfg.Options.ConnectionPriorityUpgradeThreshold
|
||||
|
||||
if bestDialerPriority >= priorityCutoff {
|
||||
if bestDialerPriority >= priorityCutoff && deviceCfg.MultipleConnections <= s.connectionsForDevice(deviceCfg.DeviceID) {
|
||||
// Our best dialer is not any better than what we already
|
||||
// have, so nothing to do here.
|
||||
// have, and we already have the desired number of
|
||||
// connections to this device,so nothing to do here.
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -666,7 +680,7 @@ func (s *service) resolveDialTargets(ctx context.Context, now time.Time, cfg con
|
||||
|
||||
dialer := dialerFactory.New(s.cfg.Options(), s.tlsCfg, s.registry, s.lanChecker)
|
||||
priority := dialer.Priority(uri.Host)
|
||||
if priority >= priorityCutoff {
|
||||
if priority >= priorityCutoff && deviceCfg.MultipleConnections <= s.connectionsForDevice(deviceCfg.DeviceID) {
|
||||
l.Debugf("Not dialing using %s as priority is not better than current connection (%d >= %d)", dialerFactory, priority, priorityCutoff)
|
||||
continue
|
||||
}
|
||||
@ -1183,6 +1197,24 @@ func (s *service) validateIdentity(c internalConn, expectedID protocol.DeviceID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *service) accountAddedConnection(d protocol.DeviceID) {
|
||||
s.connectionsMut.Lock()
|
||||
defer s.connectionsMut.Unlock()
|
||||
s.connections[d]++
|
||||
}
|
||||
|
||||
func (s *service) accountRemovedConnection(d protocol.DeviceID) {
|
||||
s.connectionsMut.Lock()
|
||||
defer s.connectionsMut.Unlock()
|
||||
s.connections[d]--
|
||||
}
|
||||
|
||||
func (s *service) connectionsForDevice(d protocol.DeviceID) int {
|
||||
s.connectionsMut.Lock()
|
||||
defer s.connectionsMut.Unlock()
|
||||
return s.connections[d]
|
||||
}
|
||||
|
||||
type nextDialRegistry map[protocol.DeviceID]nextDialDevice
|
||||
|
||||
type nextDialDevice struct {
|
||||
|
@ -37,7 +37,7 @@ func newFakeConnection(id protocol.DeviceID, model Model) *fakeConnection {
|
||||
f.closeOnce.Do(func() {
|
||||
close(f.closed)
|
||||
})
|
||||
model.Closed(f.ConnectionID(), err)
|
||||
model.Closed(f, err)
|
||||
f.ClosedReturns(f.closed)
|
||||
})
|
||||
return f
|
||||
@ -157,7 +157,7 @@ func (f *fakeConnection) sendIndexUpdate() {
|
||||
for i := range f.files {
|
||||
toSend[i] = prepareFileInfoForIndex(f.files[i])
|
||||
}
|
||||
f.model.IndexUpdate(f.id, f.folder, toSend)
|
||||
f.model.IndexUpdate(f, f.folder, toSend)
|
||||
}
|
||||
|
||||
func addFakeConn(m *testModel, dev protocol.DeviceID, folderID string) *fakeConnection {
|
||||
@ -165,7 +165,7 @@ func addFakeConn(m *testModel, dev protocol.DeviceID, folderID string) *fakeConn
|
||||
fc.folder = folderID
|
||||
m.AddConnection(fc, protocol.Hello{})
|
||||
|
||||
m.ClusterConfig(dev, protocol.ClusterConfig{
|
||||
m.ClusterConfig(fc, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: folderID,
|
||||
|
@ -45,7 +45,7 @@ func TestRecvOnlyRevertDeletes(t *testing.T) {
|
||||
|
||||
// Send and index update for the known stuff
|
||||
|
||||
must(t, m.Index(device1, "ro", knownFiles))
|
||||
must(t, m.Index(device1Conn, "ro", knownFiles))
|
||||
f.updateLocalsFromScanning(knownFiles)
|
||||
|
||||
size := globalSize(t, m, "ro")
|
||||
@ -122,7 +122,7 @@ func TestRecvOnlyRevertNeeds(t *testing.T) {
|
||||
|
||||
// Send and index update for the known stuff
|
||||
|
||||
must(t, m.Index(device1, "ro", knownFiles))
|
||||
must(t, m.Index(device1Conn, "ro", knownFiles))
|
||||
f.updateLocalsFromScanning(knownFiles)
|
||||
|
||||
// Scan the folder.
|
||||
@ -212,7 +212,7 @@ func TestRecvOnlyUndoChanges(t *testing.T) {
|
||||
|
||||
// Send an index update for the known stuff
|
||||
|
||||
must(t, m.Index(device1, "ro", knownFiles))
|
||||
must(t, m.Index(device1Conn, "ro", knownFiles))
|
||||
f.updateLocalsFromScanning(knownFiles)
|
||||
|
||||
// Scan the folder.
|
||||
@ -282,7 +282,7 @@ func TestRecvOnlyDeletedRemoteDrop(t *testing.T) {
|
||||
|
||||
// Send an index update for the known stuff
|
||||
|
||||
must(t, m.Index(device1, "ro", knownFiles))
|
||||
must(t, m.Index(device1Conn, "ro", knownFiles))
|
||||
f.updateLocalsFromScanning(knownFiles)
|
||||
|
||||
// Scan the folder.
|
||||
@ -347,7 +347,7 @@ func TestRecvOnlyRemoteUndoChanges(t *testing.T) {
|
||||
|
||||
// Send an index update for the known stuff
|
||||
|
||||
must(t, m.Index(device1, "ro", knownFiles))
|
||||
must(t, m.Index(device1Conn, "ro", knownFiles))
|
||||
f.updateLocalsFromScanning(knownFiles)
|
||||
|
||||
// Scan the folder.
|
||||
@ -402,7 +402,7 @@ func TestRecvOnlyRemoteUndoChanges(t *testing.T) {
|
||||
return true
|
||||
})
|
||||
snap.Release()
|
||||
must(t, m.IndexUpdate(device1, "ro", files))
|
||||
must(t, m.IndexUpdate(device1Conn, "ro", files))
|
||||
|
||||
// Ensure the pull to resolve conflicts (content identical) happened
|
||||
must(t, f.doInSync(func() error {
|
||||
@ -470,7 +470,7 @@ func TestRecvOnlyRevertOwnID(t *testing.T) {
|
||||
}()
|
||||
|
||||
// Receive an index update with an older version, but valid and then revert
|
||||
must(t, m.Index(device1, f.ID, []protocol.FileInfo{fi}))
|
||||
must(t, m.Index(device1Conn, f.ID, []protocol.FileInfo{fi}))
|
||||
f.Revert()
|
||||
|
||||
select {
|
||||
|
@ -1296,7 +1296,7 @@ func TestPullSymlinkOverExistingWindows(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("file missing")
|
||||
}
|
||||
must(t, m.Index(device1, f.ID, []protocol.FileInfo{{Name: name, Type: protocol.FileInfoTypeSymlink, Version: file.Version.Update(device1.Short())}}))
|
||||
must(t, m.Index(device1Conn, f.ID, []protocol.FileInfo{{Name: name, Type: protocol.FileInfoTypeSymlink, Version: file.Version.Update(device1.Short())}}))
|
||||
|
||||
scanChan := make(chan string)
|
||||
|
||||
|
@ -44,16 +44,16 @@ type Model struct {
|
||||
arg1 string
|
||||
arg2 string
|
||||
}
|
||||
ClosedStub func(string, error)
|
||||
ClosedStub func(protocol.Connection, error)
|
||||
closedMutex sync.RWMutex
|
||||
closedArgsForCall []struct {
|
||||
arg1 string
|
||||
arg1 protocol.Connection
|
||||
arg2 error
|
||||
}
|
||||
ClusterConfigStub func(protocol.DeviceID, protocol.ClusterConfig) error
|
||||
ClusterConfigStub func(protocol.Connection, protocol.ClusterConfig) error
|
||||
clusterConfigMutex sync.RWMutex
|
||||
clusterConfigArgsForCall []struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 protocol.ClusterConfig
|
||||
}
|
||||
clusterConfigReturns struct {
|
||||
@ -200,10 +200,10 @@ type Model struct {
|
||||
dismissPendingFolderReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
DownloadProgressStub func(protocol.DeviceID, string, []protocol.FileDownloadProgressUpdate) error
|
||||
DownloadProgressStub func(protocol.Connection, string, []protocol.FileDownloadProgressUpdate) error
|
||||
downloadProgressMutex sync.RWMutex
|
||||
downloadProgressArgsForCall []struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 string
|
||||
arg3 []protocol.FileDownloadProgressUpdate
|
||||
}
|
||||
@ -303,10 +303,10 @@ type Model struct {
|
||||
result1 []*model.TreeEntry
|
||||
result2 error
|
||||
}
|
||||
IndexStub func(protocol.DeviceID, string, []protocol.FileInfo) error
|
||||
IndexStub func(protocol.Connection, string, []protocol.FileInfo) error
|
||||
indexMutex sync.RWMutex
|
||||
indexArgsForCall []struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 string
|
||||
arg3 []protocol.FileInfo
|
||||
}
|
||||
@ -316,10 +316,10 @@ type Model struct {
|
||||
indexReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
IndexUpdateStub func(protocol.DeviceID, string, []protocol.FileInfo) error
|
||||
IndexUpdateStub func(protocol.Connection, string, []protocol.FileInfo) error
|
||||
indexUpdateMutex sync.RWMutex
|
||||
indexUpdateArgsForCall []struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 string
|
||||
arg3 []protocol.FileInfo
|
||||
}
|
||||
@ -447,10 +447,10 @@ type Model struct {
|
||||
result1 []db.FileInfoTruncated
|
||||
result2 error
|
||||
}
|
||||
RequestStub func(protocol.DeviceID, string, string, int32, int32, int64, []byte, uint32, bool) (protocol.RequestResponse, error)
|
||||
RequestStub func(protocol.Connection, string, string, int32, int32, int64, []byte, uint32, bool) (protocol.RequestResponse, error)
|
||||
requestMutex sync.RWMutex
|
||||
requestArgsForCall []struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 string
|
||||
arg3 string
|
||||
arg4 int32
|
||||
@ -728,10 +728,10 @@ func (fake *Model) BringToFrontArgsForCall(i int) (string, string) {
|
||||
return argsForCall.arg1, argsForCall.arg2
|
||||
}
|
||||
|
||||
func (fake *Model) Closed(arg1 string, arg2 error) {
|
||||
func (fake *Model) Closed(arg1 protocol.Connection, arg2 error) {
|
||||
fake.closedMutex.Lock()
|
||||
fake.closedArgsForCall = append(fake.closedArgsForCall, struct {
|
||||
arg1 string
|
||||
arg1 protocol.Connection
|
||||
arg2 error
|
||||
}{arg1, arg2})
|
||||
stub := fake.ClosedStub
|
||||
@ -748,24 +748,24 @@ func (fake *Model) ClosedCallCount() int {
|
||||
return len(fake.closedArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *Model) ClosedCalls(stub func(string, error)) {
|
||||
func (fake *Model) ClosedCalls(stub func(protocol.Connection, error)) {
|
||||
fake.closedMutex.Lock()
|
||||
defer fake.closedMutex.Unlock()
|
||||
fake.ClosedStub = stub
|
||||
}
|
||||
|
||||
func (fake *Model) ClosedArgsForCall(i int) (string, error) {
|
||||
func (fake *Model) ClosedArgsForCall(i int) (protocol.Connection, error) {
|
||||
fake.closedMutex.RLock()
|
||||
defer fake.closedMutex.RUnlock()
|
||||
argsForCall := fake.closedArgsForCall[i]
|
||||
return argsForCall.arg1, argsForCall.arg2
|
||||
}
|
||||
|
||||
func (fake *Model) ClusterConfig(arg1 protocol.DeviceID, arg2 protocol.ClusterConfig) error {
|
||||
func (fake *Model) ClusterConfig(arg1 protocol.Connection, arg2 protocol.ClusterConfig) error {
|
||||
fake.clusterConfigMutex.Lock()
|
||||
ret, specificReturn := fake.clusterConfigReturnsOnCall[len(fake.clusterConfigArgsForCall)]
|
||||
fake.clusterConfigArgsForCall = append(fake.clusterConfigArgsForCall, struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 protocol.ClusterConfig
|
||||
}{arg1, arg2})
|
||||
stub := fake.ClusterConfigStub
|
||||
@ -787,13 +787,13 @@ func (fake *Model) ClusterConfigCallCount() int {
|
||||
return len(fake.clusterConfigArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *Model) ClusterConfigCalls(stub func(protocol.DeviceID, protocol.ClusterConfig) error) {
|
||||
func (fake *Model) ClusterConfigCalls(stub func(protocol.Connection, protocol.ClusterConfig) error) {
|
||||
fake.clusterConfigMutex.Lock()
|
||||
defer fake.clusterConfigMutex.Unlock()
|
||||
fake.ClusterConfigStub = stub
|
||||
}
|
||||
|
||||
func (fake *Model) ClusterConfigArgsForCall(i int) (protocol.DeviceID, protocol.ClusterConfig) {
|
||||
func (fake *Model) ClusterConfigArgsForCall(i int) (protocol.Connection, protocol.ClusterConfig) {
|
||||
fake.clusterConfigMutex.RLock()
|
||||
defer fake.clusterConfigMutex.RUnlock()
|
||||
argsForCall := fake.clusterConfigArgsForCall[i]
|
||||
@ -1484,7 +1484,7 @@ func (fake *Model) DismissPendingFolderReturnsOnCall(i int, result1 error) {
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *Model) DownloadProgress(arg1 protocol.DeviceID, arg2 string, arg3 []protocol.FileDownloadProgressUpdate) error {
|
||||
func (fake *Model) DownloadProgress(arg1 protocol.Connection, arg2 string, arg3 []protocol.FileDownloadProgressUpdate) error {
|
||||
var arg3Copy []protocol.FileDownloadProgressUpdate
|
||||
if arg3 != nil {
|
||||
arg3Copy = make([]protocol.FileDownloadProgressUpdate, len(arg3))
|
||||
@ -1493,7 +1493,7 @@ func (fake *Model) DownloadProgress(arg1 protocol.DeviceID, arg2 string, arg3 []
|
||||
fake.downloadProgressMutex.Lock()
|
||||
ret, specificReturn := fake.downloadProgressReturnsOnCall[len(fake.downloadProgressArgsForCall)]
|
||||
fake.downloadProgressArgsForCall = append(fake.downloadProgressArgsForCall, struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 string
|
||||
arg3 []protocol.FileDownloadProgressUpdate
|
||||
}{arg1, arg2, arg3Copy})
|
||||
@ -1516,13 +1516,13 @@ func (fake *Model) DownloadProgressCallCount() int {
|
||||
return len(fake.downloadProgressArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *Model) DownloadProgressCalls(stub func(protocol.DeviceID, string, []protocol.FileDownloadProgressUpdate) error) {
|
||||
func (fake *Model) DownloadProgressCalls(stub func(protocol.Connection, string, []protocol.FileDownloadProgressUpdate) error) {
|
||||
fake.downloadProgressMutex.Lock()
|
||||
defer fake.downloadProgressMutex.Unlock()
|
||||
fake.DownloadProgressStub = stub
|
||||
}
|
||||
|
||||
func (fake *Model) DownloadProgressArgsForCall(i int) (protocol.DeviceID, string, []protocol.FileDownloadProgressUpdate) {
|
||||
func (fake *Model) DownloadProgressArgsForCall(i int) (protocol.Connection, string, []protocol.FileDownloadProgressUpdate) {
|
||||
fake.downloadProgressMutex.RLock()
|
||||
defer fake.downloadProgressMutex.RUnlock()
|
||||
argsForCall := fake.downloadProgressArgsForCall[i]
|
||||
@ -1990,7 +1990,7 @@ func (fake *Model) GlobalDirectoryTreeReturnsOnCall(i int, result1 []*model.Tree
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *Model) Index(arg1 protocol.DeviceID, arg2 string, arg3 []protocol.FileInfo) error {
|
||||
func (fake *Model) Index(arg1 protocol.Connection, arg2 string, arg3 []protocol.FileInfo) error {
|
||||
var arg3Copy []protocol.FileInfo
|
||||
if arg3 != nil {
|
||||
arg3Copy = make([]protocol.FileInfo, len(arg3))
|
||||
@ -1999,7 +1999,7 @@ func (fake *Model) Index(arg1 protocol.DeviceID, arg2 string, arg3 []protocol.Fi
|
||||
fake.indexMutex.Lock()
|
||||
ret, specificReturn := fake.indexReturnsOnCall[len(fake.indexArgsForCall)]
|
||||
fake.indexArgsForCall = append(fake.indexArgsForCall, struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 string
|
||||
arg3 []protocol.FileInfo
|
||||
}{arg1, arg2, arg3Copy})
|
||||
@ -2022,13 +2022,13 @@ func (fake *Model) IndexCallCount() int {
|
||||
return len(fake.indexArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *Model) IndexCalls(stub func(protocol.DeviceID, string, []protocol.FileInfo) error) {
|
||||
func (fake *Model) IndexCalls(stub func(protocol.Connection, string, []protocol.FileInfo) error) {
|
||||
fake.indexMutex.Lock()
|
||||
defer fake.indexMutex.Unlock()
|
||||
fake.IndexStub = stub
|
||||
}
|
||||
|
||||
func (fake *Model) IndexArgsForCall(i int) (protocol.DeviceID, string, []protocol.FileInfo) {
|
||||
func (fake *Model) IndexArgsForCall(i int) (protocol.Connection, string, []protocol.FileInfo) {
|
||||
fake.indexMutex.RLock()
|
||||
defer fake.indexMutex.RUnlock()
|
||||
argsForCall := fake.indexArgsForCall[i]
|
||||
@ -2058,7 +2058,7 @@ func (fake *Model) IndexReturnsOnCall(i int, result1 error) {
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *Model) IndexUpdate(arg1 protocol.DeviceID, arg2 string, arg3 []protocol.FileInfo) error {
|
||||
func (fake *Model) IndexUpdate(arg1 protocol.Connection, arg2 string, arg3 []protocol.FileInfo) error {
|
||||
var arg3Copy []protocol.FileInfo
|
||||
if arg3 != nil {
|
||||
arg3Copy = make([]protocol.FileInfo, len(arg3))
|
||||
@ -2067,7 +2067,7 @@ func (fake *Model) IndexUpdate(arg1 protocol.DeviceID, arg2 string, arg3 []proto
|
||||
fake.indexUpdateMutex.Lock()
|
||||
ret, specificReturn := fake.indexUpdateReturnsOnCall[len(fake.indexUpdateArgsForCall)]
|
||||
fake.indexUpdateArgsForCall = append(fake.indexUpdateArgsForCall, struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 string
|
||||
arg3 []protocol.FileInfo
|
||||
}{arg1, arg2, arg3Copy})
|
||||
@ -2090,13 +2090,13 @@ func (fake *Model) IndexUpdateCallCount() int {
|
||||
return len(fake.indexUpdateArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *Model) IndexUpdateCalls(stub func(protocol.DeviceID, string, []protocol.FileInfo) error) {
|
||||
func (fake *Model) IndexUpdateCalls(stub func(protocol.Connection, string, []protocol.FileInfo) error) {
|
||||
fake.indexUpdateMutex.Lock()
|
||||
defer fake.indexUpdateMutex.Unlock()
|
||||
fake.IndexUpdateStub = stub
|
||||
}
|
||||
|
||||
func (fake *Model) IndexUpdateArgsForCall(i int) (protocol.DeviceID, string, []protocol.FileInfo) {
|
||||
func (fake *Model) IndexUpdateArgsForCall(i int) (protocol.Connection, string, []protocol.FileInfo) {
|
||||
fake.indexUpdateMutex.RLock()
|
||||
defer fake.indexUpdateMutex.RUnlock()
|
||||
argsForCall := fake.indexUpdateArgsForCall[i]
|
||||
@ -2666,7 +2666,7 @@ func (fake *Model) RemoteNeedFolderFilesReturnsOnCall(i int, result1 []db.FileIn
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *Model) Request(arg1 protocol.DeviceID, arg2 string, arg3 string, arg4 int32, arg5 int32, arg6 int64, arg7 []byte, arg8 uint32, arg9 bool) (protocol.RequestResponse, error) {
|
||||
func (fake *Model) Request(arg1 protocol.Connection, arg2 string, arg3 string, arg4 int32, arg5 int32, arg6 int64, arg7 []byte, arg8 uint32, arg9 bool) (protocol.RequestResponse, error) {
|
||||
var arg7Copy []byte
|
||||
if arg7 != nil {
|
||||
arg7Copy = make([]byte, len(arg7))
|
||||
@ -2675,7 +2675,7 @@ func (fake *Model) Request(arg1 protocol.DeviceID, arg2 string, arg3 string, arg
|
||||
fake.requestMutex.Lock()
|
||||
ret, specificReturn := fake.requestReturnsOnCall[len(fake.requestArgsForCall)]
|
||||
fake.requestArgsForCall = append(fake.requestArgsForCall, struct {
|
||||
arg1 protocol.DeviceID
|
||||
arg1 protocol.Connection
|
||||
arg2 string
|
||||
arg3 string
|
||||
arg4 int32
|
||||
@ -2704,13 +2704,13 @@ func (fake *Model) RequestCallCount() int {
|
||||
return len(fake.requestArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *Model) RequestCalls(stub func(protocol.DeviceID, string, string, int32, int32, int64, []byte, uint32, bool) (protocol.RequestResponse, error)) {
|
||||
func (fake *Model) RequestCalls(stub func(protocol.Connection, string, string, int32, int32, int64, []byte, uint32, bool) (protocol.RequestResponse, error)) {
|
||||
fake.requestMutex.Lock()
|
||||
defer fake.requestMutex.Unlock()
|
||||
fake.RequestStub = stub
|
||||
}
|
||||
|
||||
func (fake *Model) RequestArgsForCall(i int) (protocol.DeviceID, string, string, int32, int32, int64, []byte, uint32, bool) {
|
||||
func (fake *Model) RequestArgsForCall(i int) (protocol.Connection, string, string, int32, int32, int64, []byte, uint32, bool) {
|
||||
fake.requestMutex.RLock()
|
||||
defer fake.requestMutex.RUnlock()
|
||||
argsForCall := fake.requestArgsForCall[i]
|
||||
|
@ -1120,14 +1120,14 @@ func (p *pager) done() bool {
|
||||
|
||||
// Index is called when a new device is connected and we receive their full index.
|
||||
// Implements the protocol.Model interface.
|
||||
func (m *model) Index(deviceID protocol.DeviceID, folder string, fs []protocol.FileInfo) error {
|
||||
return m.handleIndex(deviceID, folder, fs, false)
|
||||
func (m *model) Index(conn protocol.Connection, folder string, fs []protocol.FileInfo) error {
|
||||
return m.handleIndex(conn.ID(), folder, fs, false)
|
||||
}
|
||||
|
||||
// IndexUpdate is called for incremental updates to connected devices' indexes.
|
||||
// Implements the protocol.Model interface.
|
||||
func (m *model) IndexUpdate(deviceID protocol.DeviceID, folder string, fs []protocol.FileInfo) error {
|
||||
return m.handleIndex(deviceID, folder, fs, true)
|
||||
func (m *model) IndexUpdate(conn protocol.Connection, folder string, fs []protocol.FileInfo) error {
|
||||
return m.handleIndex(conn.ID(), folder, fs, true)
|
||||
}
|
||||
|
||||
func (m *model) handleIndex(deviceID protocol.DeviceID, folder string, fs []protocol.FileInfo, update bool) error {
|
||||
@ -1169,13 +1169,20 @@ type ClusterConfigReceivedEventData struct {
|
||||
Device protocol.DeviceID `json:"device"`
|
||||
}
|
||||
|
||||
func (m *model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterConfig) error {
|
||||
func (m *model) ClusterConfig(conn protocol.Connection, cm protocol.ClusterConfig) error {
|
||||
if cm.Secondary {
|
||||
// No handling of secondary connection ClusterConfigs; they merely
|
||||
// indicate the connection is ready to start.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check the peer device's announced folders against our own. Emits events
|
||||
// for folders that we don't expect (unknown or not shared).
|
||||
// Also, collect a list of folders we do share, and if he's interested in
|
||||
// temporary indexes, subscribe the connection.
|
||||
|
||||
l.Debugf("Handling ClusterConfig from %v", deviceID.Short())
|
||||
deviceID := conn.ID()
|
||||
l.Debugf("Handling ClusterConfig from %v/%s", deviceID.Short(), conn.ConnectionID())
|
||||
|
||||
m.pmut.RLock()
|
||||
indexHandlerRegistry, ok := m.indexHandlers[deviceID]
|
||||
@ -1788,7 +1795,10 @@ func (m *model) introduceDevice(device protocol.Device, introducerCfg config.Dev
|
||||
}
|
||||
|
||||
// Closed is called when a connection has been closed
|
||||
func (m *model) Closed(connID string, err error) {
|
||||
func (m *model) Closed(conn protocol.Connection, err error) {
|
||||
connID := conn.ConnectionID()
|
||||
deviceID := conn.ID()
|
||||
|
||||
m.pmut.Lock()
|
||||
conn, ok := m.conns[connID]
|
||||
if !ok {
|
||||
@ -1800,32 +1810,31 @@ func (m *model) Closed(connID string, err error) {
|
||||
delete(m.closed, connID)
|
||||
delete(m.conns, connID)
|
||||
|
||||
device := conn.ID()
|
||||
removedIsPrimary := m.deviceConns[device][0] == connID
|
||||
remainingConns := without(m.deviceConns[device], connID)
|
||||
removedIsPrimary := m.deviceConns[deviceID][0] == connID
|
||||
remainingConns := without(m.deviceConns[deviceID], connID)
|
||||
// XXX: all the below needs more thinking about when to remove what
|
||||
if removedIsPrimary {
|
||||
m.progressEmitter.temporaryIndexUnsubscribe(conn)
|
||||
delete(m.indexHandlers, device)
|
||||
delete(m.deviceDownloads, device)
|
||||
delete(m.indexHandlers, deviceID)
|
||||
delete(m.deviceDownloads, deviceID)
|
||||
m.scheduleConnectionPromotion()
|
||||
}
|
||||
if len(remainingConns) == 0 {
|
||||
// All device connections closed
|
||||
delete(m.deviceConns, device)
|
||||
delete(m.connRequestLimiters, device)
|
||||
delete(m.helloMessages, device)
|
||||
delete(m.remoteFolderStates, device)
|
||||
m.deviceDidClose(device, time.Since(conn.EstablishedAt()))
|
||||
delete(m.deviceConns, deviceID)
|
||||
delete(m.connRequestLimiters, deviceID)
|
||||
delete(m.helloMessages, deviceID)
|
||||
delete(m.remoteFolderStates, deviceID)
|
||||
m.deviceDidClose(deviceID, time.Since(conn.EstablishedAt()))
|
||||
} else {
|
||||
// Some connections remain
|
||||
m.deviceConns[device] = remainingConns
|
||||
m.deviceConns[deviceID] = remainingConns
|
||||
}
|
||||
m.pmut.Unlock()
|
||||
|
||||
l.Infof("Connection to %s at %s closed: %v", device, conn, err)
|
||||
l.Infof("Connection to %s at %s closed: %v", deviceID, conn, err)
|
||||
m.evLogger.Log(events.DeviceDisconnected, map[string]string{
|
||||
"id": device.String(),
|
||||
"id": deviceID.String(),
|
||||
"error": err.Error(),
|
||||
})
|
||||
close(closed)
|
||||
@ -1862,11 +1871,14 @@ func (r *requestResponse) Wait() {
|
||||
|
||||
// Request returns the specified data segment by reading it from local disk.
|
||||
// Implements the protocol.Model interface.
|
||||
func (m *model) Request(deviceID protocol.DeviceID, folder, name string, _, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (out protocol.RequestResponse, err error) {
|
||||
func (m *model) Request(conn protocol.Connection, folder, name string, _, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (out protocol.RequestResponse, err error) {
|
||||
if size < 0 || offset < 0 {
|
||||
return nil, protocol.ErrInvalid
|
||||
}
|
||||
|
||||
deviceID := conn.ID()
|
||||
connID := conn.ConnectionID()
|
||||
|
||||
m.fmut.RLock()
|
||||
folderCfg, ok := m.folderCfgs[folder]
|
||||
folderIgnores := m.folderIgnores[folder]
|
||||
@ -1894,16 +1906,16 @@ func (m *model) Request(deviceID protocol.DeviceID, folder, name string, _, size
|
||||
}
|
||||
|
||||
if deviceID != protocol.LocalDeviceID {
|
||||
l.Debugf("%v REQ(in): %s: %q / %q o=%d s=%d t=%v", m, deviceID, folder, name, offset, size, fromTemporary)
|
||||
l.Debugf("%v REQ(in): %s/%s: %q / %q o=%d s=%d t=%v", m, deviceID, connID, folder, name, offset, size, fromTemporary)
|
||||
}
|
||||
|
||||
if fs.IsInternal(name) {
|
||||
l.Debugf("%v REQ(in) for internal file: %s: %q / %q o=%d s=%d", m, deviceID, folder, name, offset, size)
|
||||
l.Debugf("%v REQ(in) for internal file: %s/%s: %q / %q o=%d s=%d", m, deviceID, connID, folder, name, offset, size)
|
||||
return nil, protocol.ErrInvalid
|
||||
}
|
||||
|
||||
if folderIgnores.Match(name).IsIgnored() {
|
||||
l.Debugf("%v REQ(in) for ignored file: %s: %q / %q o=%d s=%d", m, deviceID, folder, name, offset, size)
|
||||
l.Debugf("%v REQ(in) for ignored file: %s/%s: %q / %q o=%d s=%d", m, deviceID, connID, folder, name, offset, size)
|
||||
return nil, protocol.ErrInvalid
|
||||
}
|
||||
|
||||
@ -2281,8 +2293,6 @@ func (m *model) AddConnection(conn protocol.Connection, hello protocol.Hello) {
|
||||
|
||||
l.Infof(`Device %s client is "%s %s" named "%s" at %s`, deviceID, hello.ClientName, hello.ClientVersion, hello.DeviceName, conn)
|
||||
|
||||
conn.Start()
|
||||
|
||||
m.pmut.Unlock()
|
||||
|
||||
if (deviceCfg.Name == "" || m.cfg.Options().OverwriteRemoteDevNames) && hello.DeviceName != "" {
|
||||
@ -2319,11 +2329,29 @@ func (m *model) promoteConnections() {
|
||||
defer m.pmut.Unlock()
|
||||
|
||||
for deviceID, connIDs := range m.deviceConns {
|
||||
cm, passwords := m.generateClusterConfigFRLocked(deviceID)
|
||||
if _, ok := m.indexHandlers[deviceID]; !ok {
|
||||
// Connected device lacks and index handler. We should promote
|
||||
// Connected device lacks an index handler. We should promote
|
||||
// the primary connection to be the index handling one.
|
||||
l.Infoln("Promoting connection", connIDs[0], "to", deviceID)
|
||||
m.promoteDeviceConnectionLocked(m.conns[connIDs[0]])
|
||||
conn := m.conns[connIDs[0]]
|
||||
m.promoteDeviceConnectionLocked(conn)
|
||||
if conn.Statistics().StartedAt.IsZero() {
|
||||
conn.SetFolderPasswords(passwords)
|
||||
conn.Start()
|
||||
conn.ClusterConfig(cm)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure any new connections also get started, and an empty
|
||||
// cluster config.
|
||||
for _, connID := range connIDs[1:] {
|
||||
conn := m.conns[connID]
|
||||
if conn.Statistics().StartedAt.IsZero() {
|
||||
conn.SetFolderPasswords(passwords)
|
||||
conn.Start()
|
||||
conn.ClusterConfig(protocol.ClusterConfig{Secondary: true})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2333,35 +2361,32 @@ func (m *model) promoteDeviceConnectionLocked(conn protocol.Connection) {
|
||||
connID := conn.ConnectionID()
|
||||
|
||||
m.deviceDownloads[deviceID] = newDeviceDownloadState()
|
||||
|
||||
indexRegistry := newIndexHandlerRegistry(conn, m.deviceDownloads[deviceID], m.closed[connID], m.Supervisor, m.evLogger)
|
||||
for id, fcfg := range m.folderCfgs {
|
||||
indexRegistry.RegisterFolderState(fcfg, m.folderFiles[id], m.folderRunners[id])
|
||||
}
|
||||
m.indexHandlers[deviceID] = indexRegistry
|
||||
|
||||
cm, passwords := m.generateClusterConfigFRLocked(deviceID)
|
||||
conn.SetFolderPasswords(passwords)
|
||||
conn.ClusterConfig(cm)
|
||||
}
|
||||
|
||||
func (m *model) DownloadProgress(device protocol.DeviceID, folder string, updates []protocol.FileDownloadProgressUpdate) error {
|
||||
func (m *model) DownloadProgress(conn protocol.Connection, folder string, updates []protocol.FileDownloadProgressUpdate) error {
|
||||
deviceID := conn.ID()
|
||||
|
||||
m.fmut.RLock()
|
||||
cfg, ok := m.folderCfgs[folder]
|
||||
m.fmut.RUnlock()
|
||||
|
||||
if !ok || cfg.DisableTempIndexes || !cfg.SharedWith(device) {
|
||||
if !ok || cfg.DisableTempIndexes || !cfg.SharedWith(deviceID) {
|
||||
return nil
|
||||
}
|
||||
|
||||
m.pmut.RLock()
|
||||
downloads := m.deviceDownloads[device]
|
||||
downloads := m.deviceDownloads[deviceID]
|
||||
m.pmut.RUnlock()
|
||||
downloads.Update(folder, updates)
|
||||
state := downloads.GetBlockCounts(folder)
|
||||
|
||||
m.evLogger.Log(events.RemoteDownloadProgress, map[string]interface{}{
|
||||
"device": device.String(),
|
||||
"device": deviceID.String(),
|
||||
"folder": folder,
|
||||
"state": state,
|
||||
})
|
||||
@ -2406,7 +2431,7 @@ func (m *model) requestGlobal(ctx context.Context, deviceID protocol.DeviceID, f
|
||||
return nil, fmt.Errorf("requestGlobal: no such device: %s", deviceID)
|
||||
}
|
||||
|
||||
l.Debugf("%v REQ(out): %s: %q / %q b=%d o=%d s=%d h=%x wh=%x ft=%t", m, deviceID, folder, name, blockNo, offset, size, hash, weakHash, fromTemporary)
|
||||
l.Debugf("%v REQ(out): %s (%s): %q / %q b=%d o=%d s=%d h=%x wh=%x ft=%t", m, deviceID, conn.String(), folder, name, blockNo, offset, size, hash, weakHash, fromTemporary)
|
||||
|
||||
return conn.Request(ctx, folder, name, blockNo, offset, size, hash, weakHash, fromTemporary)
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ func TestRequest(t *testing.T) {
|
||||
m.ScanFolder("default")
|
||||
|
||||
// Existing, shared file
|
||||
res, err := m.Request(device1, "default", "foo", 0, 6, 0, nil, 0, false)
|
||||
res, err := m.Request(device1Conn, "default", "foo", 0, 6, 0, nil, 0, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -104,35 +104,35 @@ func TestRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
// Existing, nonshared file
|
||||
_, err = m.Request(device2, "default", "foo", 0, 6, 0, nil, 0, false)
|
||||
_, err = m.Request(device2Conn, "default", "foo", 0, 6, 0, nil, 0, false)
|
||||
if err == nil {
|
||||
t.Error("Unexpected nil error on insecure file read")
|
||||
}
|
||||
|
||||
// Nonexistent file
|
||||
_, err = m.Request(device1, "default", "nonexistent", 0, 6, 0, nil, 0, false)
|
||||
_, err = m.Request(device1Conn, "default", "nonexistent", 0, 6, 0, nil, 0, false)
|
||||
if err == nil {
|
||||
t.Error("Unexpected nil error on insecure file read")
|
||||
}
|
||||
|
||||
// Shared folder, but disallowed file name
|
||||
_, err = m.Request(device1, "default", "../walk.go", 0, 6, 0, nil, 0, false)
|
||||
_, err = m.Request(device1Conn, "default", "../walk.go", 0, 6, 0, nil, 0, false)
|
||||
if err == nil {
|
||||
t.Error("Unexpected nil error on insecure file read")
|
||||
}
|
||||
|
||||
// Negative offset
|
||||
_, err = m.Request(device1, "default", "foo", 0, -4, 0, nil, 0, false)
|
||||
_, err = m.Request(device1Conn, "default", "foo", 0, -4, 0, nil, 0, false)
|
||||
if err == nil {
|
||||
t.Error("Unexpected nil error on insecure file read")
|
||||
}
|
||||
|
||||
// Larger block than available
|
||||
_, err = m.Request(device1, "default", "foo", 0, 42, 0, []byte("hash necessary but not checked"), 0, false)
|
||||
_, err = m.Request(device1Conn, "default", "foo", 0, 42, 0, []byte("hash necessary but not checked"), 0, false)
|
||||
if err == nil {
|
||||
t.Error("Unexpected nil error on read past end of file")
|
||||
}
|
||||
_, err = m.Request(device1, "default", "foo", 0, 42, 0, nil, 0, false)
|
||||
_, err = m.Request(device1Conn, "default", "foo", 0, 42, 0, nil, 0, false)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error when large read should be permitted")
|
||||
}
|
||||
@ -168,11 +168,11 @@ func benchmarkIndex(b *testing.B, nfiles int) {
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem(nil).URI())
|
||||
|
||||
files := genFiles(nfiles)
|
||||
must(b, m.Index(device1, fcfg.ID, files))
|
||||
must(b, m.Index(device1Conn, fcfg.ID, files))
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
must(b, m.Index(device1, fcfg.ID, files))
|
||||
must(b, m.Index(device1Conn, fcfg.ID, files))
|
||||
}
|
||||
b.ReportAllocs()
|
||||
}
|
||||
@ -197,11 +197,11 @@ func benchmarkIndexUpdate(b *testing.B, nfiles, nufiles int) {
|
||||
files := genFiles(nfiles)
|
||||
ufiles := genFiles(nufiles)
|
||||
|
||||
must(b, m.Index(device1, fcfg.ID, files))
|
||||
must(b, m.Index(device1Conn, fcfg.ID, files))
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
must(b, m.IndexUpdate(device1, fcfg.ID, ufiles))
|
||||
must(b, m.IndexUpdate(device1Conn, fcfg.ID, ufiles))
|
||||
}
|
||||
b.ReportAllocs()
|
||||
}
|
||||
@ -218,7 +218,7 @@ func BenchmarkRequestOut(b *testing.B) {
|
||||
fc.addFile(f.Name, 0o644, protocol.FileInfoTypeFile, []byte("some data to return"))
|
||||
}
|
||||
m.AddConnection(fc, protocol.Hello{})
|
||||
must(b, m.Index(device1, "default", files))
|
||||
must(b, m.Index(device1Conn, "default", files))
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@ -247,7 +247,7 @@ func BenchmarkRequestInSingleFile(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := m.Request(device1, "default", "request/for/a/file/in/a/couple/of/dirs/128k", 0, 128<<10, 0, nil, 0, false); err != nil {
|
||||
if _, err := m.Request(device1Conn, "default", "request/for/a/file/in/a/couple/of/dirs/128k", 0, 128<<10, 0, nil, 0, false); err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
}
|
||||
@ -287,7 +287,7 @@ func TestDeviceRename(t *testing.T) {
|
||||
t.Errorf("Device already has a name")
|
||||
}
|
||||
|
||||
m.Closed(conn.ConnectionID(), protocol.ErrTimeout)
|
||||
m.Closed(conn, protocol.ErrTimeout)
|
||||
hello.DeviceName = "tester"
|
||||
m.AddConnection(conn, hello)
|
||||
|
||||
@ -295,7 +295,7 @@ func TestDeviceRename(t *testing.T) {
|
||||
t.Errorf("Device did not get a name")
|
||||
}
|
||||
|
||||
m.Closed(conn.ConnectionID(), protocol.ErrTimeout)
|
||||
m.Closed(conn, protocol.ErrTimeout)
|
||||
hello.DeviceName = "tester2"
|
||||
m.AddConnection(conn, hello)
|
||||
|
||||
@ -317,7 +317,7 @@ func TestDeviceRename(t *testing.T) {
|
||||
t.Errorf("Device name not saved in config")
|
||||
}
|
||||
|
||||
m.Closed(conn.ConnectionID(), protocol.ErrTimeout)
|
||||
m.Closed(conn, protocol.ErrTimeout)
|
||||
|
||||
waiter, err := cfg.Modify(func(cfg *config.Configuration) {
|
||||
cfg.Options.OverwriteRemoteDevNames = true
|
||||
@ -528,7 +528,7 @@ func TestIntroducer(t *testing.T) {
|
||||
SkipIntroductionRemovals: true,
|
||||
EncryptionPasswordToken: []byte("faketoken"),
|
||||
})
|
||||
m.ClusterConfig(device1, cc)
|
||||
m.ClusterConfig(device1Conn, cc)
|
||||
|
||||
if newDev, ok := m.cfg.Device(device2); !ok || !newDev.Introducer || !newDev.SkipIntroductionRemovals {
|
||||
t.Error("device 2 missing or wrong flags")
|
||||
@ -584,7 +584,7 @@ func TestIntroducer(t *testing.T) {
|
||||
Introducer: true,
|
||||
SkipIntroductionRemovals: true,
|
||||
})
|
||||
m.ClusterConfig(device1, cc)
|
||||
m.ClusterConfig(device1Conn, cc)
|
||||
|
||||
// Should not get introducer, as it's already unset, and it's an existing device.
|
||||
if newDev, ok := m.cfg.Device(device2); !ok || newDev.Introducer || newDev.SkipIntroductionRemovals {
|
||||
@ -634,7 +634,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{})
|
||||
m.ClusterConfig(device1Conn, protocol.ClusterConfig{})
|
||||
|
||||
if _, ok := m.cfg.Device(device2); ok {
|
||||
t.Error("device 2 should have been removed")
|
||||
@ -686,7 +686,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{})
|
||||
m.ClusterConfig(device1Conn, protocol.ClusterConfig{})
|
||||
|
||||
if _, ok := m.cfg.Device(device2); !ok {
|
||||
t.Error("device 2 should not have been removed")
|
||||
@ -743,7 +743,7 @@ func TestIntroducer(t *testing.T) {
|
||||
Introducer: true,
|
||||
SkipIntroductionRemovals: true,
|
||||
})
|
||||
m.ClusterConfig(device1, cc)
|
||||
m.ClusterConfig(device1Conn, cc)
|
||||
|
||||
if _, ok := m.cfg.Device(device2); !ok {
|
||||
t.Error("device 2 should not have been removed")
|
||||
@ -794,7 +794,7 @@ func TestIntroducer(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{})
|
||||
m.ClusterConfig(device1Conn, protocol.ClusterConfig{})
|
||||
|
||||
if _, ok := m.cfg.Device(device2); !ok {
|
||||
t.Error("device 2 should not have been removed")
|
||||
@ -847,7 +847,7 @@ func TestIntroducer(t *testing.T) {
|
||||
})
|
||||
defer cleanupModel(m)
|
||||
defer cancel()
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{})
|
||||
m.ClusterConfig(device1Conn, protocol.ClusterConfig{})
|
||||
|
||||
if _, ok := m.cfg.Device(device2); !ok {
|
||||
t.Error("device 2 should not have been removed")
|
||||
@ -906,14 +906,14 @@ func TestIssue5063(t *testing.T) {
|
||||
for _, c := range m.conns {
|
||||
conn := c.(*fakeConnection)
|
||||
conn.CloseCalls(func(_ error) {})
|
||||
defer m.Closed(c.ConnectionID(), errStopped) // to unblock deferred m.Stop()
|
||||
defer m.Closed(c, errStopped) // to unblock deferred m.Stop()
|
||||
}
|
||||
m.pmut.Unlock()
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
addAndVerify := func(id string) {
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id))
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
|
||||
t.Error("expected shared", id)
|
||||
}
|
||||
@ -951,7 +951,7 @@ func TestAutoAcceptRejected(t *testing.T) {
|
||||
// defer cleanupModel(m)
|
||||
defer cancel()
|
||||
id := srand.String(8)
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id))
|
||||
|
||||
if cfg, ok := m.cfg.Folder(id); ok && cfg.SharedWith(device1) {
|
||||
t.Error("unexpected shared", id)
|
||||
@ -964,7 +964,7 @@ func TestAutoAcceptNewFolder(t *testing.T) {
|
||||
defer cleanupModel(m)
|
||||
defer cancel()
|
||||
id := srand.String(8)
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id))
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
|
||||
t.Error("expected shared", id)
|
||||
}
|
||||
@ -976,14 +976,14 @@ func TestAutoAcceptNewFolderFromTwoDevices(t *testing.T) {
|
||||
defer cancel()
|
||||
id := srand.String(8)
|
||||
defer os.RemoveAll(id)
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id))
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
|
||||
t.Error("expected shared", id)
|
||||
}
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || fcfg.SharedWith(device2) {
|
||||
t.Error("unexpected expected shared", id)
|
||||
}
|
||||
m.ClusterConfig(device2, createClusterConfig(device2, id))
|
||||
m.ClusterConfig(device2Conn, createClusterConfig(device2, id))
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || !fcfg.SharedWith(device2) {
|
||||
t.Error("expected shared", id)
|
||||
}
|
||||
@ -997,14 +997,14 @@ func TestAutoAcceptNewFolderFromOnlyOneDevice(t *testing.T) {
|
||||
defer os.RemoveAll(id)
|
||||
defer cleanupModel(m)
|
||||
defer cancel()
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id))
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
|
||||
t.Error("expected shared", id)
|
||||
}
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || fcfg.SharedWith(device2) {
|
||||
t.Error("unexpected expected shared", id)
|
||||
}
|
||||
m.ClusterConfig(device2, createClusterConfig(device2, id))
|
||||
m.ClusterConfig(device2Conn, createClusterConfig(device2, id))
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || fcfg.SharedWith(device2) {
|
||||
t.Error("unexpected shared", id)
|
||||
}
|
||||
@ -1035,10 +1035,10 @@ func TestAutoAcceptNewFolderPremutationsNoPanic(t *testing.T) {
|
||||
cfg.Folders = append(cfg.Folders, fcfg)
|
||||
}
|
||||
m, cancel := newState(t, cfg)
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
m.ClusterConfig(device1Conn, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{dev1folder},
|
||||
})
|
||||
m.ClusterConfig(device2, protocol.ClusterConfig{
|
||||
m.ClusterConfig(device2Conn, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{dev2folder},
|
||||
})
|
||||
cleanupModel(m)
|
||||
@ -1058,7 +1058,7 @@ func TestAutoAcceptMultipleFolders(t *testing.T) {
|
||||
m, cancel := newState(t, defaultAutoAcceptCfg)
|
||||
defer cleanupModel(m)
|
||||
defer cancel()
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id1, id2))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id1, id2))
|
||||
if fcfg, ok := m.cfg.Folder(id1); !ok || !fcfg.SharedWith(device1) {
|
||||
t.Error("expected shared", id1)
|
||||
}
|
||||
@ -1086,7 +1086,7 @@ func TestAutoAcceptExistingFolder(t *testing.T) {
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || fcfg.SharedWith(device1) {
|
||||
t.Error("missing folder, or shared", id)
|
||||
}
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id))
|
||||
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || !fcfg.SharedWith(device1) || fcfg.Path != idOther {
|
||||
t.Error("missing folder, or unshared, or path changed", id)
|
||||
@ -1112,7 +1112,7 @@ func TestAutoAcceptNewAndExistingFolder(t *testing.T) {
|
||||
if fcfg, ok := m.cfg.Folder(id1); !ok || fcfg.SharedWith(device1) {
|
||||
t.Error("missing folder, or shared", id1)
|
||||
}
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id1, id2))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id1, id2))
|
||||
|
||||
for i, id := range []string{id1, id2} {
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
|
||||
@ -1143,7 +1143,7 @@ func TestAutoAcceptAlreadyShared(t *testing.T) {
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
|
||||
t.Error("missing folder, or not shared", id)
|
||||
}
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id))
|
||||
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
|
||||
t.Error("missing folder, or not shared", id)
|
||||
@ -1159,7 +1159,7 @@ func TestAutoAcceptNameConflict(t *testing.T) {
|
||||
m, cancel := newState(t, defaultAutoAcceptCfg)
|
||||
defer cleanupModel(m)
|
||||
defer cancel()
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
m.ClusterConfig(device1Conn, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
@ -1179,7 +1179,7 @@ func TestAutoAcceptPrefersLabel(t *testing.T) {
|
||||
label := srand.String(8)
|
||||
defer cleanupModel(m)
|
||||
defer cancel()
|
||||
m.ClusterConfig(device1, addFolderDevicesToClusterConfig(protocol.ClusterConfig{
|
||||
m.ClusterConfig(device1Conn, addFolderDevicesToClusterConfig(protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
@ -1203,7 +1203,7 @@ func TestAutoAcceptFallsBackToID(t *testing.T) {
|
||||
}
|
||||
defer cleanupModel(m)
|
||||
defer cancel()
|
||||
m.ClusterConfig(device1, addFolderDevicesToClusterConfig(protocol.ClusterConfig{
|
||||
m.ClusterConfig(device1Conn, addFolderDevicesToClusterConfig(protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: id,
|
||||
@ -1245,7 +1245,7 @@ func TestAutoAcceptPausedWhenFolderConfigChanged(t *testing.T) {
|
||||
t.Fatal("folder running?")
|
||||
}
|
||||
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id))
|
||||
m.generateClusterConfig(device1)
|
||||
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok {
|
||||
@ -1294,7 +1294,7 @@ func TestAutoAcceptPausedWhenFolderConfigNotChanged(t *testing.T) {
|
||||
t.Fatal("folder running?")
|
||||
}
|
||||
|
||||
m.ClusterConfig(device1, createClusterConfig(device1, id))
|
||||
m.ClusterConfig(device1Conn, createClusterConfig(device1, id))
|
||||
m.generateClusterConfig(device1)
|
||||
|
||||
if fcfg, ok := m.cfg.Folder(id); !ok {
|
||||
@ -1338,7 +1338,7 @@ func TestAutoAcceptEnc(t *testing.T) {
|
||||
// would panic.
|
||||
clusterConfig := func(deviceID protocol.DeviceID, cm protocol.ClusterConfig) {
|
||||
m.AddConnection(newFakeConnection(deviceID, m), protocol.Hello{})
|
||||
m.ClusterConfig(deviceID, cm)
|
||||
m.ClusterConfig(&protocolmocks.Connection{IDStub: func() protocol.DeviceID { return deviceID }}, cm)
|
||||
}
|
||||
|
||||
clusterConfig(device1, basicCC())
|
||||
@ -1806,7 +1806,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
must(t, m.Index(device1, "default", testdata))
|
||||
must(t, m.Index(device1Conn, "default", testdata))
|
||||
|
||||
result, _ := m.GlobalDirectoryTree("default", "", -1, false)
|
||||
|
||||
@ -2013,7 +2013,7 @@ func benchmarkTree(b *testing.B, n1, n2 int) {
|
||||
m.ScanFolder(fcfg.ID)
|
||||
files := genDeepFiles(n1, n2)
|
||||
|
||||
must(b, m.Index(device1, fcfg.ID, files))
|
||||
must(b, m.Index(device1Conn, fcfg.ID, files))
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@ -2159,7 +2159,7 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
|
||||
conn2 := newFakeConnection(device2, m)
|
||||
m.AddConnection(conn2, protocol.Hello{})
|
||||
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
m.ClusterConfig(device1Conn, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: "default",
|
||||
@ -2171,7 +2171,7 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.ClusterConfig(device2, protocol.ClusterConfig{
|
||||
m.ClusterConfig(device2Conn, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: "default",
|
||||
@ -2424,7 +2424,7 @@ func TestRemoveDirWithContent(t *testing.T) {
|
||||
file.Deleted = true
|
||||
file.Version = file.Version.Update(device1.Short()).Update(device1.Short())
|
||||
|
||||
must(t, m.IndexUpdate(device1, fcfg.ID, []protocol.FileInfo{dir, file}))
|
||||
must(t, m.IndexUpdate(device1Conn, fcfg.ID, []protocol.FileInfo{dir, file}))
|
||||
|
||||
// Is there something we could trigger on instead of just waiting?
|
||||
timeout := time.NewTimer(5 * time.Second)
|
||||
@ -2919,14 +2919,14 @@ func TestRequestLimit(t *testing.T) {
|
||||
m.ScanFolder("default")
|
||||
|
||||
befReq := time.Now()
|
||||
first, err := m.Request(device1, "default", file, 0, 2000, 0, nil, 0, false)
|
||||
first, err := m.Request(device1Conn, "default", file, 0, 2000, 0, nil, 0, false)
|
||||
if err != nil {
|
||||
t.Fatalf("First request failed: %v", err)
|
||||
}
|
||||
reqDur := time.Since(befReq)
|
||||
returned := make(chan struct{})
|
||||
go func() {
|
||||
second, err := m.Request(device1, "default", file, 0, 2000, 0, nil, 0, false)
|
||||
second, err := m.Request(device1Conn, "default", file, 0, 2000, 0, nil, 0, false)
|
||||
if err != nil {
|
||||
t.Errorf("Second request failed: %v", err)
|
||||
}
|
||||
@ -2964,13 +2964,15 @@ func TestConnCloseOnRestart(t *testing.T) {
|
||||
|
||||
br := &testutils.BlockingRW{}
|
||||
nw := &testutils.NoopRW{}
|
||||
conn := protocol.NewConnection(device1, br, nw, testutils.NoopCloser{}, m, new(protocolmocks.ConnectionInfo), protocol.CompressionNever, nil, m.keyGen)
|
||||
m.AddConnection(conn, protocol.Hello{})
|
||||
m.AddConnection(protocol.NewConnection(device1, br, nw, testutils.NoopCloser{}, m, new(protocolmocks.ConnectionInfo), protocol.CompressionNever, nil, m.keyGen), protocol.Hello{})
|
||||
m.pmut.RLock()
|
||||
if len(m.closed) != 1 {
|
||||
t.Fatalf("Expected just one conn (len(m.conns) == %v)", len(m.conns))
|
||||
t.Fatalf("Expected just one conn (len(m.closed) == %v)", len(m.closed))
|
||||
}
|
||||
var closed chan struct{}
|
||||
for _, c := range m.closed {
|
||||
closed = c
|
||||
}
|
||||
closed := m.closed[conn.ConnectionID()]
|
||||
m.pmut.RUnlock()
|
||||
|
||||
waiter, err := w.RemoveDevice(device1)
|
||||
@ -3065,7 +3067,10 @@ func TestDevicePause(t *testing.T) {
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
m.pmut.RLock()
|
||||
closed := m.closed[m.deviceConns[device1][0]]
|
||||
var closed chan struct{}
|
||||
for _, c := range m.closed {
|
||||
closed = c
|
||||
}
|
||||
m.pmut.RUnlock()
|
||||
|
||||
pauseDevice(t, m.cfg, device1, true)
|
||||
@ -3581,7 +3586,7 @@ func TestScanDeletedROChangedOnSR(t *testing.T) {
|
||||
}
|
||||
// A remote must have the file, otherwise the deletion below is
|
||||
// automatically resolved as not a ro-changed item.
|
||||
must(t, m.IndexUpdate(device1, fcfg.ID, []protocol.FileInfo{file}))
|
||||
must(t, m.IndexUpdate(device1Conn, fcfg.ID, []protocol.FileInfo{file}))
|
||||
|
||||
must(t, ffs.Remove(name))
|
||||
m.ScanFolders()
|
||||
@ -3694,9 +3699,9 @@ func TestIssue6961(t *testing.T) {
|
||||
version := protocol.Vector{}.Update(device1.Short())
|
||||
|
||||
// Remote, valid and existing file
|
||||
must(t, m.Index(device1, fcfg.ID, []protocol.FileInfo{{Name: name, Version: version, Sequence: 1}}))
|
||||
must(t, m.Index(device1Conn, fcfg.ID, []protocol.FileInfo{{Name: name, Version: version, Sequence: 1}}))
|
||||
// Remote, invalid (receive-only) and existing file
|
||||
must(t, m.Index(device2, fcfg.ID, []protocol.FileInfo{{Name: name, RawInvalid: true, Sequence: 1}}))
|
||||
must(t, m.Index(device2Conn, fcfg.ID, []protocol.FileInfo{{Name: name, RawInvalid: true, Sequence: 1}}))
|
||||
// Create a local file
|
||||
if fd, err := tfs.OpenFile(name, fs.OptCreate, 0o666); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -3722,7 +3727,7 @@ func TestIssue6961(t *testing.T) {
|
||||
m.ScanFolders()
|
||||
|
||||
// Drop the remote index, add some other file.
|
||||
must(t, m.Index(device2, fcfg.ID, []protocol.FileInfo{{Name: "bar", RawInvalid: true, Sequence: 1}}))
|
||||
must(t, m.Index(device2Conn, fcfg.ID, []protocol.FileInfo{{Name: "bar", RawInvalid: true, Sequence: 1}}))
|
||||
|
||||
// Pause and unpause folder to create new db.FileSet and thus recalculate everything
|
||||
pauseFolder(t, wcfg, fcfg.ID, true)
|
||||
@ -3745,7 +3750,7 @@ func TestCompletionEmptyGlobal(t *testing.T) {
|
||||
m.fmut.Unlock()
|
||||
files[0].Deleted = true
|
||||
files[0].Version = files[0].Version.Update(device1.Short())
|
||||
must(t, m.IndexUpdate(device1, fcfg.ID, files))
|
||||
must(t, m.IndexUpdate(device1Conn, fcfg.ID, files))
|
||||
comp := m.testCompletion(protocol.LocalDeviceID, fcfg.ID)
|
||||
if comp.CompletionPct != 95 {
|
||||
t.Error("Expected completion of 95%, got", comp.CompletionPct)
|
||||
@ -3766,26 +3771,26 @@ func TestNeedMetaAfterIndexReset(t *testing.T) {
|
||||
|
||||
// Start with two remotes having one file, then both deleting it, then
|
||||
// only one adding it again.
|
||||
must(t, m.Index(device1, fcfg.ID, files))
|
||||
must(t, m.Index(device2, fcfg.ID, files))
|
||||
must(t, m.Index(device1Conn, fcfg.ID, files))
|
||||
must(t, m.Index(device2Conn, fcfg.ID, files))
|
||||
seq++
|
||||
files[0].SetDeleted(device2.Short())
|
||||
files[0].Sequence = seq
|
||||
must(t, m.IndexUpdate(device2, fcfg.ID, files))
|
||||
must(t, m.IndexUpdate(device1, fcfg.ID, files))
|
||||
must(t, m.IndexUpdate(device2Conn, fcfg.ID, files))
|
||||
must(t, m.IndexUpdate(device1Conn, fcfg.ID, files))
|
||||
seq++
|
||||
files[0].Deleted = false
|
||||
files[0].Size = 20
|
||||
files[0].Version = files[0].Version.Update(device1.Short())
|
||||
files[0].Sequence = seq
|
||||
must(t, m.IndexUpdate(device1, fcfg.ID, files))
|
||||
must(t, m.IndexUpdate(device1Conn, fcfg.ID, files))
|
||||
|
||||
if comp := m.testCompletion(device2, fcfg.ID); comp.NeedItems != 1 {
|
||||
t.Error("Expected one needed item for device2, got", comp.NeedItems)
|
||||
}
|
||||
|
||||
// Pretend we had an index reset on device 1
|
||||
must(t, m.Index(device1, fcfg.ID, files))
|
||||
must(t, m.Index(device1Conn, fcfg.ID, files))
|
||||
if comp := m.testCompletion(device2, fcfg.ID); comp.NeedItems != 1 {
|
||||
t.Error("Expected one needed item for device2, got", comp.NeedItems)
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ func TestSymlinkTraversalRead(t *testing.T) {
|
||||
<-done
|
||||
|
||||
// Request a file by traversing the symlink
|
||||
res, err := m.Request(device1, "default", "symlink/requests_test.go", 0, 10, 0, nil, 0, false)
|
||||
res, err := m.Request(device1Conn, "default", "symlink/requests_test.go", 0, 10, 0, nil, 0, false)
|
||||
if err == nil || res != nil {
|
||||
t.Error("Managed to traverse symlink")
|
||||
}
|
||||
@ -439,7 +439,7 @@ func TestRescanIfHaveInvalidContent(t *testing.T) {
|
||||
t.Fatalf("unexpected weak hash: %d != 103547413", f.Blocks[0].WeakHash)
|
||||
}
|
||||
|
||||
res, err := m.Request(device1, "default", "foo", 0, int32(len(payload)), 0, f.Blocks[0].Hash, f.Blocks[0].WeakHash, false)
|
||||
res, err := m.Request(device1Conn, "default", "foo", 0, int32(len(payload)), 0, f.Blocks[0].Hash, f.Blocks[0].WeakHash, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -453,7 +453,7 @@ func TestRescanIfHaveInvalidContent(t *testing.T) {
|
||||
|
||||
writeFile(t, tfs, "foo", payload)
|
||||
|
||||
_, err = m.Request(device1, "default", "foo", 0, int32(len(payload)), 0, f.Blocks[0].Hash, f.Blocks[0].WeakHash, false)
|
||||
_, err = m.Request(device1Conn, "default", "foo", 0, int32(len(payload)), 0, f.Blocks[0].Hash, f.Blocks[0].WeakHash, false)
|
||||
if err == nil {
|
||||
t.Fatalf("expected failure")
|
||||
}
|
||||
@ -1122,7 +1122,7 @@ func TestRequestIndexSenderPause(t *testing.T) {
|
||||
|
||||
cc := basicClusterConfig(device1, myID, fcfg.ID)
|
||||
cc.Folders[0].Paused = true
|
||||
m.ClusterConfig(device1, cc)
|
||||
m.ClusterConfig(device1Conn, cc)
|
||||
|
||||
seq++
|
||||
files[0].Sequence = seq
|
||||
@ -1143,7 +1143,7 @@ func TestRequestIndexSenderPause(t *testing.T) {
|
||||
// Remote unpaused
|
||||
|
||||
cc.Folders[0].Paused = false
|
||||
m.ClusterConfig(device1, cc)
|
||||
m.ClusterConfig(device1Conn, cc)
|
||||
select {
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("timed out before receiving index")
|
||||
@ -1168,12 +1168,12 @@ func TestRequestIndexSenderPause(t *testing.T) {
|
||||
// Local and remote paused, then first resume remote, then local
|
||||
|
||||
cc.Folders[0].Paused = true
|
||||
m.ClusterConfig(device1, cc)
|
||||
m.ClusterConfig(device1Conn, cc)
|
||||
|
||||
pauseFolder(t, m.cfg, fcfg.ID, true)
|
||||
|
||||
cc.Folders[0].Paused = false
|
||||
m.ClusterConfig(device1, cc)
|
||||
m.ClusterConfig(device1Conn, cc)
|
||||
|
||||
pauseFolder(t, m.cfg, fcfg.ID, false)
|
||||
|
||||
@ -1190,7 +1190,7 @@ func TestRequestIndexSenderPause(t *testing.T) {
|
||||
// Folder removed on remote
|
||||
|
||||
cc = protocol.ClusterConfig{}
|
||||
m.ClusterConfig(device1, cc)
|
||||
m.ClusterConfig(device1Conn, cc)
|
||||
|
||||
seq++
|
||||
files[0].Sequence = seq
|
||||
@ -1304,7 +1304,7 @@ func TestRequestReceiveEncrypted(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
m.AddConnection(fc, protocol.Hello{})
|
||||
m.ClusterConfig(device1, protocol.ClusterConfig{
|
||||
m.ClusterConfig(device1Conn, protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: "default",
|
||||
@ -1354,7 +1354,7 @@ func TestRequestReceiveEncrypted(t *testing.T) {
|
||||
}
|
||||
|
||||
// Simulate request from device that is untrusted too, i.e. with non-empty, but garbage hash
|
||||
_, err := m.Request(device1, fcfg.ID, name, 0, 1064, 0, []byte("garbage"), 0, false)
|
||||
_, err := m.Request(device1Conn, fcfg.ID, name, 0, 1064, 0, []byte("garbage"), 0, false)
|
||||
must(t, err)
|
||||
|
||||
changed, err := m.LocalChangedFolderFiles(fcfg.ID, 1, 10)
|
||||
@ -1405,7 +1405,7 @@ func TestRequestGlobalInvalidToValid(t *testing.T) {
|
||||
file := fc.files[0]
|
||||
fc.mut.Unlock()
|
||||
file.SetIgnored()
|
||||
m.IndexUpdate(device2, fcfg.ID, []protocol.FileInfo{prepareFileInfoForIndex(file)})
|
||||
m.IndexUpdate(device2Conn, fcfg.ID, []protocol.FileInfo{prepareFileInfoForIndex(file)})
|
||||
|
||||
// Wait for the ignored file to be received and possible pulled
|
||||
timeout := time.After(10 * time.Second)
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/protocol/mocks"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
)
|
||||
|
||||
@ -29,6 +30,16 @@ var (
|
||||
defaultFolderConfig config.FolderConfiguration
|
||||
defaultCfg config.Configuration
|
||||
defaultAutoAcceptCfg config.Configuration
|
||||
device1Conn = &mocks.Connection{
|
||||
IDStub: func() protocol.DeviceID {
|
||||
return device1
|
||||
},
|
||||
}
|
||||
device2Conn = &mocks.Connection{
|
||||
IDStub: func() protocol.DeviceID {
|
||||
return device2
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -167,15 +167,15 @@ func negotiateTLS(cert tls.Certificate, conn0, conn1 net.Conn) (net.Conn, net.Co
|
||||
|
||||
type fakeModel struct{}
|
||||
|
||||
func (*fakeModel) Index(_ DeviceID, _ string, _ []FileInfo) error {
|
||||
func (*fakeModel) Index(Connection, string, []FileInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*fakeModel) IndexUpdate(_ DeviceID, _ string, _ []FileInfo) error {
|
||||
func (*fakeModel) IndexUpdate(Connection, string, []FileInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*fakeModel) Request(_ DeviceID, _, _ string, _, size int32, offset int64, _ []byte, _ uint32, _ bool) (RequestResponse, error) {
|
||||
func (*fakeModel) Request(_ Connection, _, _ string, _, size int32, offset int64, _ []byte, _ uint32, _ bool) (RequestResponse, error) {
|
||||
// We write the offset to the end of the buffer, so the receiver
|
||||
// can verify that it did in fact get some data back over the
|
||||
// connection.
|
||||
@ -184,13 +184,13 @@ func (*fakeModel) Request(_ DeviceID, _, _ string, _, size int32, offset int64,
|
||||
return &fakeRequestResponse{buf}, nil
|
||||
}
|
||||
|
||||
func (*fakeModel) ClusterConfig(_ DeviceID, _ ClusterConfig) error {
|
||||
func (*fakeModel) ClusterConfig(Connection, ClusterConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*fakeModel) Closed(string, error) {
|
||||
func (*fakeModel) Closed(Connection, error) {
|
||||
}
|
||||
|
||||
func (*fakeModel) DownloadProgress(_ DeviceID, _ string, _ []FileDownloadProgressUpdate) error {
|
||||
func (*fakeModel) DownloadProgress(Connection, string, []FileDownloadProgressUpdate) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -289,6 +289,7 @@ var xxx_messageInfo_Header proto.InternalMessageInfo
|
||||
|
||||
type ClusterConfig struct {
|
||||
Folders []Folder `protobuf:"bytes,1,rep,name=folders,proto3" json:"folders" xml:"folder"`
|
||||
Secondary bool `protobuf:"varint,2,opt,name=secondary,proto3" json:"secondary" xml:"secondary"`
|
||||
}
|
||||
|
||||
func (m *ClusterConfig) Reset() { *m = ClusterConfig{} }
|
||||
@ -1142,205 +1143,206 @@ func init() {
|
||||
func init() { proto.RegisterFile("lib/protocol/bep.proto", fileDescriptor_311ef540e10d9705) }
|
||||
|
||||
var fileDescriptor_311ef540e10d9705 = []byte{
|
||||
// 3163 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5a, 0x4d, 0x6c, 0x1b, 0xc7,
|
||||
0xbd, 0x17, 0xc5, 0x0f, 0x51, 0x23, 0xc9, 0xa6, 0xc6, 0x5f, 0x0c, 0x6d, 0x6b, 0xf9, 0x26, 0xce,
|
||||
0x7b, 0x8a, 0xf2, 0x62, 0x27, 0xca, 0xc7, 0xcb, 0x8b, 0xf3, 0x1c, 0x88, 0x22, 0x25, 0x33, 0x96,
|
||||
0x49, 0x65, 0x28, 0xdb, 0xb1, 0xf1, 0x1e, 0x88, 0x15, 0x77, 0x44, 0x2d, 0x4c, 0xee, 0xf2, 0xed,
|
||||
0x52, 0x5f, 0x41, 0x2f, 0x6d, 0x80, 0x20, 0xd0, 0xa1, 0x28, 0x72, 0x2a, 0x8a, 0x0a, 0x0d, 0x7a,
|
||||
0xe9, 0xad, 0x40, 0x0f, 0xbd, 0xe4, 0xd4, 0xa3, 0x8f, 0x46, 0x80, 0x02, 0x45, 0x0f, 0x0b, 0xc4,
|
||||
0xbe, 0xb4, 0xec, 0x8d, 0xc7, 0x9e, 0x8a, 0xf9, 0xcf, 0xec, 0xec, 0xac, 0x3e, 0x52, 0x39, 0x39,
|
||||
0xf4, 0x64, 0xfe, 0x7f, 0xff, 0xdf, 0xff, 0xbf, 0xb3, 0xf3, 0xff, 0x9a, 0x59, 0x19, 0x5d, 0xec,
|
||||
0xd8, 0xeb, 0x37, 0x7a, 0x9e, 0xdb, 0x77, 0x5b, 0x6e, 0xe7, 0xc6, 0x3a, 0xeb, 0x5d, 0x07, 0x01,
|
||||
0x67, 0x43, 0xac, 0x30, 0xce, 0x76, 0xfb, 0x02, 0x2c, 0xbc, 0xec, 0xb1, 0x9e, 0xeb, 0x0b, 0xfa,
|
||||
0xfa, 0xd6, 0xc6, 0x8d, 0xb6, 0xdb, 0x76, 0x41, 0x80, 0x5f, 0x82, 0x44, 0x9e, 0x25, 0x50, 0xfa,
|
||||
0x36, 0xeb, 0x74, 0x5c, 0xbc, 0x88, 0x26, 0x2c, 0xb6, 0x6d, 0xb7, 0x58, 0xd3, 0x31, 0xbb, 0x2c,
|
||||
0x9f, 0x28, 0x26, 0x66, 0xc7, 0x4b, 0x64, 0x10, 0x18, 0x48, 0xc0, 0x35, 0xb3, 0xcb, 0x86, 0x81,
|
||||
0x91, 0xdb, 0xed, 0x76, 0xde, 0x27, 0x11, 0x44, 0xa8, 0xa6, 0xe7, 0x4e, 0x5a, 0x1d, 0x9b, 0x39,
|
||||
0x7d, 0xe1, 0x64, 0x34, 0x72, 0x22, 0xe0, 0x98, 0x93, 0x08, 0x22, 0x54, 0xd3, 0xe3, 0x3a, 0x3a,
|
||||
0x23, 0x9d, 0x6c, 0x33, 0xcf, 0xb7, 0x5d, 0x27, 0x9f, 0x04, 0x3f, 0xb3, 0x83, 0xc0, 0x98, 0x12,
|
||||
0x9a, 0xfb, 0x42, 0x31, 0x0c, 0x8c, 0x73, 0x9a, 0x2b, 0x89, 0x12, 0x1a, 0x67, 0x91, 0xdf, 0x25,
|
||||
0x50, 0xe6, 0x36, 0x33, 0x2d, 0xe6, 0xe1, 0x05, 0x94, 0xea, 0xef, 0xf5, 0xc4, 0xeb, 0x9d, 0x99,
|
||||
0xbf, 0x70, 0x3d, 0xdc, 0xb8, 0xeb, 0x77, 0x99, 0xef, 0x9b, 0x6d, 0xb6, 0xb6, 0xd7, 0x63, 0xa5,
|
||||
0x8b, 0x83, 0xc0, 0x00, 0xda, 0x30, 0x30, 0x10, 0xf8, 0xe7, 0x02, 0xa1, 0x80, 0x61, 0x0b, 0x4d,
|
||||
0xb4, 0xdc, 0x6e, 0xcf, 0x63, 0x3e, 0xac, 0x6d, 0x14, 0x3c, 0x5d, 0x39, 0xe2, 0x69, 0x31, 0xe2,
|
||||
0x94, 0xae, 0x0d, 0x02, 0x43, 0x37, 0x1a, 0x06, 0xc6, 0xb4, 0x58, 0x77, 0x84, 0x11, 0xaa, 0x33,
|
||||
0xc8, 0xff, 0xa2, 0xa9, 0xc5, 0xce, 0x96, 0xdf, 0x67, 0xde, 0xa2, 0xeb, 0x6c, 0xd8, 0x6d, 0x7c,
|
||||
0x07, 0x8d, 0x6d, 0xb8, 0x1d, 0x8b, 0x79, 0x7e, 0x3e, 0x51, 0x4c, 0xce, 0x4e, 0xcc, 0xe7, 0xa2,
|
||||
0x47, 0x2e, 0x81, 0xa2, 0x64, 0x3c, 0x09, 0x8c, 0x91, 0x41, 0x60, 0x84, 0xc4, 0x61, 0x60, 0x4c,
|
||||
0xc2, 0x63, 0x84, 0x4c, 0x68, 0xa8, 0x20, 0x5f, 0xa7, 0x50, 0x46, 0x18, 0xe1, 0xeb, 0x68, 0xd4,
|
||||
0xb6, 0x64, 0xb8, 0x67, 0x9e, 0x05, 0xc6, 0x68, 0xb5, 0x3c, 0x08, 0x8c, 0x51, 0xdb, 0x1a, 0x06,
|
||||
0x46, 0x16, 0xac, 0x6d, 0x8b, 0x7c, 0xf9, 0xf4, 0xda, 0x68, 0xb5, 0x4c, 0x47, 0x6d, 0x0b, 0x5f,
|
||||
0x47, 0xe9, 0x8e, 0xb9, 0xce, 0x3a, 0x32, 0xb8, 0xf9, 0x41, 0x60, 0x08, 0x60, 0x18, 0x18, 0x13,
|
||||
0xc0, 0x07, 0x89, 0x50, 0x81, 0xe2, 0x9b, 0x68, 0xdc, 0x63, 0xa6, 0xd5, 0x74, 0x9d, 0xce, 0x1e,
|
||||
0x04, 0x32, 0x5b, 0x9a, 0x19, 0x04, 0x46, 0x96, 0x83, 0x75, 0xa7, 0xb3, 0x37, 0x0c, 0x8c, 0x33,
|
||||
0x60, 0x16, 0x02, 0x84, 0x2a, 0x1d, 0x6e, 0x22, 0x6c, 0xb7, 0x1d, 0xd7, 0x63, 0xcd, 0x1e, 0xf3,
|
||||
0xba, 0x36, 0x6c, 0x8d, 0x9f, 0x4f, 0x81, 0x97, 0x37, 0x06, 0x81, 0x31, 0x2d, 0xb4, 0xab, 0x91,
|
||||
0x72, 0x18, 0x18, 0x97, 0xc4, 0xaa, 0x0f, 0x6b, 0x08, 0x3d, 0xca, 0xc6, 0x77, 0xd0, 0x94, 0x7c,
|
||||
0x80, 0xc5, 0x3a, 0xac, 0xcf, 0xf2, 0x69, 0xf0, 0xfd, 0xef, 0x83, 0xc0, 0x98, 0x14, 0x8a, 0x32,
|
||||
0xe0, 0xc3, 0xc0, 0xc0, 0x9a, 0x5b, 0x01, 0x12, 0x1a, 0xe3, 0x60, 0x0b, 0x9d, 0xb7, 0x6c, 0xdf,
|
||||
0x5c, 0xef, 0xb0, 0x66, 0x9f, 0x75, 0x7b, 0x4d, 0xdb, 0xb1, 0xd8, 0x2e, 0xf3, 0xf3, 0x19, 0xf0,
|
||||
0x39, 0x3f, 0x08, 0x0c, 0x2c, 0xf5, 0x6b, 0xac, 0xdb, 0xab, 0x0a, 0xed, 0x30, 0x30, 0xf2, 0xa2,
|
||||
0xa6, 0x8e, 0xa8, 0x08, 0x3d, 0x86, 0x8f, 0xe7, 0x51, 0xa6, 0x67, 0x6e, 0xf9, 0xcc, 0xca, 0x8f,
|
||||
0x81, 0xdf, 0xc2, 0x20, 0x30, 0x24, 0xa2, 0x02, 0x2e, 0x44, 0x42, 0x25, 0xce, 0x93, 0x47, 0x54,
|
||||
0xa9, 0x9f, 0xcf, 0x1d, 0x4e, 0x9e, 0x32, 0x28, 0xa2, 0xe4, 0x91, 0x44, 0xe5, 0x4b, 0xc8, 0x84,
|
||||
0x86, 0x0a, 0xf2, 0x87, 0x0c, 0xca, 0x08, 0x23, 0x5c, 0x52, 0xc9, 0x33, 0x59, 0x9a, 0xe7, 0x0e,
|
||||
0xfe, 0x1c, 0x18, 0x59, 0xa1, 0xab, 0x96, 0x4f, 0x4a, 0xa6, 0x2f, 0x9e, 0x5e, 0x4b, 0x68, 0x09,
|
||||
0x35, 0x87, 0x52, 0x5a, 0xb3, 0x80, 0xda, 0x73, 0x44, 0x9b, 0x10, 0xb5, 0xe7, 0x40, 0x83, 0x00,
|
||||
0x0c, 0x7f, 0x80, 0xc6, 0x4d, 0xcb, 0xe2, 0x35, 0xc2, 0xfc, 0x7c, 0xb2, 0x98, 0xe4, 0x39, 0x3b,
|
||||
0x08, 0x8c, 0x08, 0x1c, 0x06, 0xc6, 0x14, 0x58, 0x49, 0x84, 0xd0, 0x48, 0x87, 0xff, 0x2f, 0x5e,
|
||||
0xb9, 0xa9, 0xc3, 0x3d, 0xe0, 0x87, 0x95, 0x2c, 0xcf, 0xf4, 0x16, 0xf3, 0x64, 0xeb, 0x4b, 0x8b,
|
||||
0x82, 0xe2, 0x99, 0xce, 0x41, 0xd9, 0xf8, 0x44, 0xa6, 0x87, 0x00, 0xa1, 0x4a, 0x87, 0x97, 0xd1,
|
||||
0x64, 0xd7, 0xdc, 0x6d, 0xfa, 0xec, 0xff, 0xb7, 0x98, 0xd3, 0x62, 0x90, 0x33, 0x49, 0xb1, 0x8a,
|
||||
0xae, 0xb9, 0xdb, 0x90, 0xb0, 0x5a, 0x85, 0x86, 0x11, 0xaa, 0x33, 0x70, 0x09, 0x21, 0xdb, 0xe9,
|
||||
0x7b, 0xae, 0xb5, 0xd5, 0x62, 0x9e, 0x4c, 0x11, 0xe8, 0xc0, 0x11, 0xaa, 0x3a, 0x70, 0x04, 0x11,
|
||||
0xaa, 0xe9, 0x71, 0x1b, 0x65, 0x21, 0x77, 0x9b, 0xb6, 0x95, 0xcf, 0x16, 0x13, 0xb3, 0xa9, 0xd2,
|
||||
0x8a, 0x0c, 0xee, 0x18, 0x64, 0x21, 0xc4, 0x36, 0xfc, 0xc9, 0x73, 0x06, 0xd8, 0x55, 0x4b, 0xed,
|
||||
0xbe, 0x94, 0x79, 0xdf, 0x08, 0x69, 0xbf, 0x88, 0x7e, 0xd2, 0x90, 0x8f, 0x7f, 0x84, 0x0a, 0xfe,
|
||||
0x63, 0x9b, 0x57, 0x8a, 0x78, 0x76, 0xdf, 0x76, 0x9d, 0xa6, 0xc7, 0xba, 0xee, 0xb6, 0xd9, 0xf1,
|
||||
0xf3, 0xe3, 0xb0, 0xf8, 0x5b, 0x83, 0xc0, 0xc8, 0x73, 0x56, 0x55, 0x23, 0x51, 0xc9, 0x19, 0x06,
|
||||
0xc6, 0x0c, 0x3c, 0xf1, 0x24, 0x02, 0xa1, 0x27, 0xda, 0xe2, 0x5d, 0xf4, 0x12, 0x73, 0x5a, 0xde,
|
||||
0x5e, 0x0f, 0x1e, 0xdb, 0x33, 0x7d, 0x7f, 0xc7, 0xf5, 0xac, 0x66, 0xdf, 0x7d, 0xcc, 0x9c, 0x3c,
|
||||
0x82, 0xa4, 0xfe, 0x60, 0x10, 0x18, 0x97, 0x22, 0xd2, 0xaa, 0xe4, 0xac, 0x71, 0xca, 0x30, 0x30,
|
||||
0xae, 0xc2, 0xb3, 0x4f, 0xd0, 0x13, 0x7a, 0x92, 0x25, 0xf9, 0x49, 0x02, 0xa5, 0x61, 0x33, 0x78,
|
||||
0x35, 0x8b, 0xa6, 0x2c, 0x5b, 0x30, 0x54, 0xb3, 0x40, 0x8e, 0xb4, 0x6f, 0x89, 0xe3, 0x0a, 0x4a,
|
||||
0x6f, 0xd8, 0x1d, 0xe6, 0xe7, 0x47, 0xa1, 0x96, 0xb1, 0x36, 0x08, 0xec, 0x0e, 0xab, 0x3a, 0x1b,
|
||||
0x6e, 0xe9, 0xb2, 0xac, 0x66, 0x41, 0x54, 0xb5, 0xc4, 0x25, 0x42, 0x05, 0x48, 0xbe, 0x48, 0xa0,
|
||||
0x09, 0x58, 0xc4, 0xbd, 0x9e, 0x65, 0xf6, 0xd9, 0xbf, 0x72, 0x29, 0x9f, 0x4f, 0xa1, 0x6c, 0x68,
|
||||
0xa0, 0x1a, 0x42, 0xe2, 0x14, 0x0d, 0x61, 0x0e, 0xa5, 0x7c, 0xfb, 0x53, 0x06, 0x83, 0x25, 0x29,
|
||||
0xb8, 0x5c, 0x56, 0x5c, 0x2e, 0x10, 0x0a, 0x18, 0xfe, 0x10, 0xa1, 0xae, 0x6b, 0xd9, 0x1b, 0x36,
|
||||
0xb3, 0x9a, 0x3e, 0x14, 0x68, 0xb2, 0x54, 0xe4, 0xdd, 0x23, 0x44, 0x1b, 0xc3, 0xc0, 0x38, 0x2b,
|
||||
0xca, 0x2b, 0x44, 0x08, 0x8d, 0xb4, 0xbc, 0x7f, 0x28, 0x07, 0xeb, 0x7b, 0xf9, 0x49, 0xa8, 0x8c,
|
||||
0x0f, 0xc2, 0xca, 0x68, 0x6c, 0xba, 0x5e, 0x1f, 0xca, 0x41, 0x3d, 0xa6, 0xb4, 0xa7, 0x4a, 0x2d,
|
||||
0x82, 0x08, 0xaf, 0x04, 0x49, 0xa6, 0x1a, 0x15, 0xaf, 0xa0, 0xb1, 0xf0, 0xc0, 0xc3, 0x33, 0x3f,
|
||||
0xd6, 0xa4, 0xef, 0xb3, 0x56, 0xdf, 0xf5, 0x4a, 0xc5, 0xb0, 0x49, 0x6f, 0xab, 0x03, 0x90, 0x28,
|
||||
0xb8, 0xed, 0xf0, 0xe8, 0x13, 0x6a, 0xf0, 0xfb, 0x28, 0xab, 0x9a, 0x09, 0x82, 0x77, 0x85, 0x66,
|
||||
0xe4, 0x47, 0x9d, 0x44, 0x34, 0x23, 0x5f, 0xb5, 0x11, 0xa5, 0xc3, 0x1f, 0xa1, 0xcc, 0x7a, 0xc7,
|
||||
0x6d, 0x3d, 0x0e, 0xa7, 0xc5, 0xb9, 0x68, 0x21, 0x25, 0x8e, 0x43, 0x5c, 0xaf, 0xca, 0xb5, 0x48,
|
||||
0xaa, 0x1a, 0xff, 0x20, 0x12, 0x2a, 0x61, 0x7e, 0x9a, 0xf3, 0xf7, 0xba, 0x1d, 0xdb, 0x79, 0xdc,
|
||||
0xec, 0x9b, 0x5e, 0x9b, 0xf5, 0xf3, 0xd3, 0xd1, 0x69, 0x4e, 0x6a, 0xd6, 0x40, 0xa1, 0x4e, 0x73,
|
||||
0x31, 0x94, 0xd0, 0x38, 0x8b, 0x9f, 0x31, 0x85, 0xeb, 0xe6, 0xa6, 0xe9, 0x6f, 0xe6, 0x31, 0xd4,
|
||||
0x29, 0x74, 0x38, 0x01, 0xdf, 0x36, 0xfd, 0x4d, 0xb5, 0xed, 0x11, 0x44, 0xa8, 0xa6, 0xc7, 0xb7,
|
||||
0xd0, 0xb8, 0xac, 0x4d, 0x66, 0xe5, 0xcf, 0x81, 0x0b, 0x48, 0x05, 0x05, 0xaa, 0x54, 0x50, 0x08,
|
||||
0xa1, 0x91, 0x16, 0x97, 0xe4, 0x39, 0x52, 0x9c, 0xfe, 0x2e, 0x1e, 0x4d, 0xfb, 0x53, 0x1c, 0x24,
|
||||
0x97, 0xd0, 0xc4, 0xe1, 0x53, 0xcd, 0x94, 0xe8, 0xf8, 0xbd, 0xd8, 0x79, 0x46, 0x74, 0xfc, 0x9e,
|
||||
0x7e, 0x92, 0xd1, 0x19, 0xf8, 0x23, 0x2d, 0x2d, 0x1d, 0x3f, 0x3f, 0x51, 0x4c, 0xcc, 0xa6, 0x4b,
|
||||
0xaf, 0xea, 0x79, 0x58, 0xf3, 0x8f, 0xe4, 0x61, 0xcd, 0x27, 0x7f, 0x0f, 0x8c, 0xa4, 0xed, 0xf4,
|
||||
0xa9, 0x46, 0xc3, 0x1b, 0x48, 0xec, 0x52, 0x13, 0xaa, 0x6a, 0x0a, 0x5c, 0x2d, 0x3f, 0x0b, 0x8c,
|
||||
0x49, 0x6a, 0xee, 0x40, 0xe8, 0x1b, 0xf6, 0xa7, 0x8c, 0x6f, 0xd4, 0x7a, 0x28, 0xa8, 0x8d, 0x52,
|
||||
0x48, 0xe8, 0xf8, 0xcb, 0xa7, 0xd7, 0x62, 0x66, 0x34, 0x32, 0xc2, 0xf7, 0x51, 0xb6, 0xd7, 0x31,
|
||||
0xfb, 0x1b, 0xae, 0xd7, 0xcd, 0x9f, 0x81, 0x64, 0xd7, 0xf6, 0x70, 0x55, 0x6a, 0xca, 0x66, 0xdf,
|
||||
0x2c, 0x11, 0x99, 0x66, 0x8a, 0xaf, 0x32, 0x37, 0x04, 0x08, 0x55, 0x3a, 0x5c, 0x46, 0x13, 0x1d,
|
||||
0xb7, 0x65, 0x76, 0x9a, 0x1b, 0x1d, 0xb3, 0xed, 0xe7, 0xff, 0x32, 0x06, 0x9b, 0x0a, 0xd9, 0x01,
|
||||
0xf8, 0x12, 0x87, 0xd5, 0x66, 0x44, 0x10, 0xa1, 0x9a, 0x1e, 0xdf, 0x46, 0x93, 0xb2, 0x8c, 0x44,
|
||||
0x8e, 0xfd, 0x75, 0x0c, 0x32, 0x04, 0x62, 0x23, 0x15, 0x32, 0xcb, 0xa6, 0xf5, 0xea, 0x13, 0x69,
|
||||
0xa6, 0x33, 0xf0, 0xc7, 0xe8, 0xac, 0xed, 0xb8, 0x16, 0x6b, 0xb6, 0x36, 0x4d, 0xa7, 0xcd, 0x78,
|
||||
0x7c, 0x06, 0x63, 0x50, 0x8d, 0x90, 0xff, 0xa0, 0x5b, 0x04, 0x15, 0xc4, 0xe8, 0x9c, 0x9c, 0x9e,
|
||||
0x1a, 0x4a, 0x68, 0x9c, 0x85, 0x77, 0x91, 0x36, 0x56, 0x9a, 0x7d, 0xcf, 0xb4, 0x3b, 0xcc, 0x13,
|
||||
0xf1, 0xfa, 0xdb, 0x18, 0x04, 0xec, 0xc3, 0x41, 0x60, 0x5c, 0x88, 0x38, 0x6b, 0x82, 0x22, 0x83,
|
||||
0x75, 0xf9, 0xd0, 0xc8, 0xd2, 0xb4, 0x2a, 0x23, 0x8e, 0x37, 0xc6, 0xef, 0xf2, 0x53, 0x24, 0x3f,
|
||||
0xe9, 0x5a, 0xf2, 0x48, 0x7b, 0x45, 0x9c, 0x17, 0x01, 0x52, 0xad, 0x48, 0xca, 0x70, 0x60, 0x84,
|
||||
0x5f, 0x98, 0xa2, 0x31, 0xdb, 0xd9, 0x36, 0x3b, 0x76, 0x78, 0x64, 0x7d, 0xef, 0x59, 0x60, 0x20,
|
||||
0x6a, 0xee, 0x54, 0x05, 0x2a, 0x4e, 0x10, 0xf0, 0x53, 0x3b, 0x41, 0x80, 0xcc, 0x4f, 0x10, 0x1a,
|
||||
0x93, 0x86, 0x3c, 0xde, 0x56, 0x1c, 0x37, 0x76, 0x2b, 0xc8, 0x82, 0x6b, 0xd8, 0x56, 0xc7, 0x8d,
|
||||
0xdf, 0x08, 0xc4, 0xb6, 0xc6, 0x50, 0x42, 0xe3, 0xac, 0xf7, 0x53, 0x3f, 0xff, 0xca, 0x18, 0x21,
|
||||
0xdf, 0x26, 0xd0, 0xb8, 0x6a, 0x71, 0x7c, 0xba, 0x40, 0xfc, 0x93, 0x10, 0x7e, 0xa8, 0xe6, 0x4d,
|
||||
0x11, 0x77, 0x51, 0xcd, 0x9b, 0x10, 0x70, 0xc0, 0xf8, 0xf4, 0x74, 0x37, 0x36, 0x7c, 0xd6, 0x87,
|
||||
0xb9, 0x95, 0x14, 0xd3, 0x53, 0x20, 0x6a, 0x7a, 0x0a, 0x91, 0x50, 0x89, 0xe3, 0x37, 0xe5, 0xf4,
|
||||
0x1a, 0x85, 0xb0, 0x5d, 0x3d, 0x7e, 0x7a, 0x85, 0x41, 0x11, 0x43, 0xec, 0x26, 0x1a, 0xdf, 0x61,
|
||||
0xe6, 0x63, 0x91, 0x97, 0xa2, 0x65, 0x40, 0x5f, 0xe7, 0xa0, 0xcc, 0x49, 0x51, 0x1d, 0x21, 0x40,
|
||||
0xa8, 0xd2, 0xc9, 0x77, 0x7c, 0x84, 0x32, 0x62, 0x9c, 0xe0, 0x55, 0x94, 0x6d, 0xb9, 0x5b, 0x4e,
|
||||
0x3f, 0xba, 0x54, 0x4e, 0xeb, 0xa7, 0x61, 0xd0, 0x94, 0xfe, 0x2d, 0x2c, 0xc0, 0x90, 0xaa, 0x62,
|
||||
0x24, 0x01, 0x7e, 0x8c, 0x95, 0x2a, 0xf2, 0x59, 0x02, 0x8d, 0x49, 0x43, 0x7c, 0x5b, 0x5d, 0x0e,
|
||||
0x52, 0xa5, 0xf7, 0x0e, 0x4d, 0xc9, 0xef, 0xbe, 0x68, 0xea, 0x13, 0x52, 0xde, 0x39, 0xb7, 0xcd,
|
||||
0xce, 0x96, 0xd8, 0xa8, 0x94, 0xb8, 0x73, 0x02, 0xa0, 0x86, 0x0e, 0x48, 0x84, 0x0a, 0x94, 0x7c,
|
||||
0x96, 0x42, 0x93, 0x7a, 0x13, 0xe1, 0xed, 0x7a, 0xcb, 0xb1, 0x77, 0x61, 0x31, 0xb1, 0x53, 0xca,
|
||||
0x3d, 0xc7, 0xde, 0x85, 0x36, 0x53, 0x78, 0x12, 0x18, 0x09, 0x1e, 0x00, 0xce, 0x53, 0x01, 0xe0,
|
||||
0x02, 0xa1, 0x80, 0xe1, 0x8f, 0xd1, 0xd8, 0x8e, 0xed, 0x58, 0xee, 0x8e, 0x0f, 0xcb, 0x98, 0xd0,
|
||||
0x6f, 0x0e, 0x0f, 0x84, 0x02, 0x3c, 0x15, 0xa5, 0xa7, 0x90, 0xad, 0xb6, 0x4b, 0xca, 0x84, 0x86,
|
||||
0x1a, 0xbc, 0x8c, 0xd2, 0x1d, 0xdb, 0xd9, 0xda, 0x85, 0x04, 0x8b, 0x8d, 0xd9, 0x4f, 0xcc, 0x7e,
|
||||
0xdf, 0x03, 0x77, 0x57, 0xa4, 0x3b, 0xc1, 0x8c, 0x2e, 0xd9, 0x5c, 0xe2, 0x97, 0x6c, 0xfe, 0x2f,
|
||||
0xbe, 0x83, 0x32, 0x96, 0xe9, 0xed, 0xd8, 0xe2, 0x52, 0x73, 0x82, 0xa7, 0x19, 0xe9, 0x49, 0x52,
|
||||
0xa3, 0x0b, 0x1e, 0x88, 0x84, 0x4a, 0x1c, 0x33, 0x34, 0xb6, 0xe1, 0x31, 0xb6, 0xee, 0x5b, 0x70,
|
||||
0x48, 0x3a, 0xc1, 0xdb, 0xbb, 0xdc, 0x1b, 0xbf, 0x06, 0x2c, 0x79, 0x8c, 0x95, 0x1a, 0x70, 0x0d,
|
||||
0x90, 0x66, 0xea, 0x8d, 0xa5, 0x0c, 0xd7, 0x00, 0x49, 0xa3, 0x21, 0x09, 0x37, 0x51, 0xc6, 0x61,
|
||||
0x7d, 0xfe, 0x94, 0xcc, 0xc9, 0x4f, 0x99, 0x97, 0x4f, 0xc9, 0xd4, 0x58, 0x5f, 0x3c, 0x44, 0x1a,
|
||||
0xa9, 0xd5, 0x0b, 0x91, 0x3f, 0x42, 0x72, 0xa8, 0x64, 0x90, 0xcf, 0x47, 0x51, 0x36, 0x8c, 0x2f,
|
||||
0x3f, 0xfc, 0xb9, 0x3b, 0x0e, 0xf3, 0xf4, 0xaf, 0x5b, 0x30, 0xf1, 0x01, 0x95, 0xd7, 0x33, 0x31,
|
||||
0xc8, 0x14, 0x42, 0x68, 0xa4, 0xe5, 0x0e, 0xda, 0x9e, 0xbb, 0xd5, 0xd3, 0xbf, 0x6c, 0x81, 0x03,
|
||||
0x40, 0x63, 0x0e, 0x14, 0x42, 0x68, 0xa4, 0xc5, 0x37, 0x51, 0x72, 0xcb, 0xb6, 0x20, 0xd4, 0xe9,
|
||||
0xd2, 0xab, 0xcf, 0x02, 0x23, 0x79, 0x0f, 0x2a, 0x80, 0xa3, 0xc3, 0xc0, 0x18, 0x17, 0x09, 0x67,
|
||||
0x5b, 0xda, 0xf8, 0xe4, 0x0c, 0xca, 0xf5, 0xdc, 0xb8, 0x6d, 0x5b, 0x10, 0x5d, 0x69, 0xbc, 0x2c,
|
||||
0x8c, 0xdb, 0x9a, 0x71, 0x3b, 0x6e, 0xbc, 0xcc, 0x8d, 0x39, 0xf6, 0xcb, 0x04, 0x9a, 0xd0, 0x32,
|
||||
0xf4, 0x87, 0xef, 0xc5, 0x0a, 0x3a, 0x23, 0x1c, 0xd8, 0x7e, 0x13, 0x5e, 0x10, 0xf6, 0x43, 0x7e,
|
||||
0x36, 0x01, 0x4d, 0xd5, 0x5f, 0xe6, 0xb8, 0xfa, 0x6c, 0xa2, 0x83, 0x84, 0xc6, 0x38, 0xa4, 0x81,
|
||||
0xc6, 0x55, 0xc0, 0xf1, 0x12, 0xca, 0xec, 0x72, 0x21, 0x6c, 0x48, 0x67, 0x0f, 0x65, 0x45, 0x74,
|
||||
0xec, 0x14, 0x34, 0x55, 0x10, 0x20, 0x12, 0x2a, 0x61, 0xd2, 0x42, 0x69, 0xe0, 0xbf, 0xd0, 0x6d,
|
||||
0x22, 0xd6, 0x67, 0x26, 0xff, 0x79, 0x9f, 0xf9, 0x71, 0x0a, 0x8d, 0x51, 0x7e, 0x68, 0xf6, 0xfb,
|
||||
0xf8, 0x1d, 0xd5, 0xed, 0xd2, 0xa5, 0x57, 0x4e, 0x6a, 0x6f, 0x51, 0x74, 0xc2, 0xaf, 0x1f, 0xd1,
|
||||
0xa5, 0x6b, 0xf4, 0xd4, 0x97, 0xae, 0xf0, 0x95, 0x92, 0xa7, 0x78, 0xa5, 0x68, 0x2c, 0xa5, 0x5e,
|
||||
0x78, 0x2c, 0xa5, 0x4f, 0x3f, 0x96, 0xc2, 0x49, 0x99, 0x39, 0xc5, 0xa4, 0xac, 0xa3, 0x33, 0x1b,
|
||||
0x9e, 0xdb, 0x85, 0x6f, 0x64, 0xae, 0x67, 0x7a, 0x7b, 0xf2, 0x54, 0x00, 0xa3, 0x9b, 0x6b, 0xd6,
|
||||
0x42, 0x85, 0x1a, 0xdd, 0x31, 0x94, 0xd0, 0x38, 0x2b, 0x3e, 0x13, 0xb3, 0x2f, 0x36, 0x13, 0xf1,
|
||||
0x2d, 0x94, 0x15, 0x27, 0x5e, 0xc7, 0x85, 0x6b, 0x57, 0xba, 0xf4, 0x32, 0x6f, 0x65, 0x80, 0xd5,
|
||||
0x5c, 0xd5, 0xca, 0xa4, 0xac, 0x5e, 0x3b, 0x24, 0x90, 0xdf, 0x26, 0x50, 0x96, 0x32, 0xbf, 0xe7,
|
||||
0x3a, 0x3e, 0xfb, 0xbe, 0x49, 0x30, 0x87, 0x52, 0x96, 0xd9, 0x37, 0x65, 0xda, 0xc1, 0xee, 0x71,
|
||||
0x59, 0xed, 0x1e, 0x17, 0x08, 0x05, 0x0c, 0x7f, 0x88, 0x52, 0x2d, 0xd7, 0x12, 0xc1, 0x3f, 0xa3,
|
||||
0x37, 0xcd, 0x8a, 0xe7, 0xb9, 0xde, 0xa2, 0x6b, 0xc9, 0x6b, 0x07, 0x27, 0x29, 0x07, 0x5c, 0x20,
|
||||
0x14, 0x30, 0xf2, 0x9b, 0x04, 0xca, 0x95, 0xdd, 0x1d, 0xa7, 0xe3, 0x9a, 0xd6, 0xaa, 0xe7, 0xb6,
|
||||
0x3d, 0xe6, 0xfb, 0xdf, 0xeb, 0xee, 0xdf, 0x44, 0x63, 0x5b, 0xf0, 0xe5, 0x20, 0xbc, 0xfd, 0x5f,
|
||||
0x8b, 0x5f, 0x83, 0x0e, 0x3f, 0x44, 0x7c, 0x66, 0x88, 0x3e, 0x34, 0x4a, 0x63, 0xe5, 0x5f, 0xc8,
|
||||
0x84, 0x86, 0x0a, 0xf2, 0xeb, 0x24, 0x2a, 0x9c, 0xec, 0x08, 0x77, 0xd1, 0x84, 0x60, 0x36, 0xb5,
|
||||
0x4f, 0xfa, 0xb3, 0xa7, 0x59, 0x03, 0x5c, 0xce, 0xe0, 0x52, 0xb0, 0xa5, 0x64, 0x75, 0x29, 0x88,
|
||||
0x20, 0x42, 0x35, 0xfd, 0x0b, 0x7d, 0xa7, 0xd4, 0xae, 0xf2, 0xc9, 0x1f, 0x7e, 0x95, 0x6f, 0xa0,
|
||||
0x29, 0x91, 0xa2, 0xe1, 0x07, 0xe5, 0x54, 0x31, 0x39, 0x9b, 0x2e, 0x5d, 0xe7, 0xdd, 0x76, 0x5d,
|
||||
0x1c, 0x56, 0xc3, 0x4f, 0xc9, 0xd3, 0x51, 0xb2, 0x0a, 0x30, 0xcc, 0xb6, 0xdc, 0x08, 0x8d, 0x71,
|
||||
0xf1, 0x52, 0xec, 0xa6, 0x27, 0x4a, 0xfd, 0x3f, 0x4e, 0x79, 0xb3, 0xd3, 0x6e, 0x72, 0x24, 0x83,
|
||||
0x52, 0xab, 0xb6, 0xd3, 0x26, 0x37, 0x51, 0x7a, 0xb1, 0xe3, 0xfa, 0xd0, 0x71, 0x3c, 0x66, 0xfa,
|
||||
0xae, 0xa3, 0xa7, 0x92, 0x40, 0x54, 0xa8, 0x85, 0x48, 0xa8, 0xc4, 0xe7, 0xbe, 0x4e, 0xa2, 0x09,
|
||||
0xed, 0x2f, 0x30, 0xf8, 0x7f, 0xd0, 0xe5, 0xbb, 0x95, 0x46, 0x63, 0x61, 0xb9, 0xd2, 0x5c, 0x7b,
|
||||
0xb8, 0x5a, 0x69, 0x2e, 0xae, 0xdc, 0x6b, 0xac, 0x55, 0x68, 0x73, 0xb1, 0x5e, 0x5b, 0xaa, 0x2e,
|
||||
0xe7, 0x46, 0x0a, 0x57, 0xf6, 0x0f, 0x8a, 0x79, 0xcd, 0x22, 0xfe, 0xb7, 0x92, 0xff, 0x44, 0x38,
|
||||
0x66, 0x5e, 0xad, 0x95, 0x2b, 0x9f, 0xe4, 0x12, 0x85, 0xf3, 0xfb, 0x07, 0xc5, 0x9c, 0x66, 0x25,
|
||||
0x3e, 0xc1, 0xfd, 0x37, 0x7a, 0xe9, 0x28, 0xbb, 0x79, 0x6f, 0xb5, 0xbc, 0xb0, 0x56, 0xc9, 0x8d,
|
||||
0x16, 0x0a, 0xfb, 0x07, 0xc5, 0x8b, 0x87, 0x8d, 0x64, 0x0a, 0xbe, 0x81, 0xce, 0xc7, 0x4c, 0x69,
|
||||
0xe5, 0xe3, 0x7b, 0x95, 0xc6, 0x5a, 0x2e, 0x59, 0xb8, 0xb8, 0x7f, 0x50, 0xc4, 0x9a, 0x55, 0x38,
|
||||
0x26, 0xe6, 0xd1, 0x85, 0x43, 0x16, 0x8d, 0xd5, 0x7a, 0xad, 0x51, 0xc9, 0xa5, 0x0a, 0x97, 0xf6,
|
||||
0x0f, 0x8a, 0xe7, 0x62, 0x26, 0xb2, 0xab, 0x2c, 0xa2, 0x99, 0x98, 0x4d, 0xb9, 0xfe, 0xa0, 0xb6,
|
||||
0x52, 0x5f, 0x28, 0x37, 0x57, 0x69, 0x7d, 0x99, 0x56, 0x1a, 0x8d, 0x5c, 0xba, 0x60, 0xec, 0x1f,
|
||||
0x14, 0x2f, 0x6b, 0xc6, 0x47, 0x2a, 0x7c, 0x0e, 0x4d, 0xc7, 0x9c, 0xac, 0x56, 0x6b, 0xcb, 0xb9,
|
||||
0x4c, 0xe1, 0xdc, 0xfe, 0x41, 0xf1, 0xac, 0x66, 0xc7, 0x63, 0x79, 0x64, 0xff, 0x16, 0x57, 0xea,
|
||||
0x8d, 0x4a, 0x6e, 0xec, 0xc8, 0xfe, 0x41, 0xc0, 0xe7, 0x7e, 0x95, 0x40, 0xf8, 0xe8, 0x1f, 0xbd,
|
||||
0xf0, 0x7b, 0x28, 0x1f, 0x3a, 0x59, 0xac, 0xdf, 0x5d, 0xe5, 0xeb, 0xac, 0xd6, 0x6b, 0xcd, 0x5a,
|
||||
0xbd, 0x56, 0xc9, 0x8d, 0xc4, 0x76, 0x55, 0xb3, 0xaa, 0xb9, 0x0e, 0xc3, 0x75, 0x74, 0xe9, 0x38,
|
||||
0xcb, 0x95, 0x47, 0x6f, 0xe7, 0x12, 0x85, 0xf9, 0xfd, 0x83, 0xe2, 0x85, 0xa3, 0x86, 0x2b, 0x8f,
|
||||
0xde, 0xfe, 0xe6, 0xa7, 0xaf, 0x1c, 0xaf, 0x98, 0xe3, 0x07, 0x20, 0x7d, 0x69, 0x6f, 0xa2, 0xf3,
|
||||
0xba, 0xe3, 0xbb, 0x95, 0xb5, 0x85, 0xf2, 0xc2, 0xda, 0x42, 0x6e, 0x44, 0xc4, 0x40, 0xa3, 0xde,
|
||||
0x65, 0x7d, 0x13, 0xda, 0xee, 0x6b, 0x68, 0x3a, 0xf6, 0x16, 0x95, 0xfb, 0x15, 0x1a, 0x66, 0x94,
|
||||
0xbe, 0x7e, 0xb6, 0xcd, 0x3c, 0xfc, 0x3a, 0xc2, 0x3a, 0x79, 0x61, 0xe5, 0xc1, 0xc2, 0xc3, 0x46,
|
||||
0x6e, 0xb4, 0x70, 0x61, 0xff, 0xa0, 0x38, 0xad, 0xb1, 0x17, 0x3a, 0x3b, 0xe6, 0x9e, 0x3f, 0xf7,
|
||||
0xfb, 0x51, 0x34, 0xa9, 0x7f, 0x37, 0xc2, 0xaf, 0xa3, 0x73, 0x4b, 0xd5, 0x15, 0x9e, 0x89, 0x4b,
|
||||
0x75, 0x11, 0x01, 0x2e, 0xe6, 0x46, 0xc4, 0xe3, 0x74, 0x2a, 0xff, 0x8d, 0xff, 0x0b, 0xe5, 0x0f,
|
||||
0xd1, 0xcb, 0x55, 0x5a, 0x59, 0x5c, 0xab, 0xd3, 0x87, 0xb9, 0x44, 0xe1, 0x25, 0xbe, 0x61, 0xba,
|
||||
0x4d, 0xd9, 0xf6, 0xa0, 0x05, 0xed, 0xe1, 0x5b, 0xe8, 0xf2, 0x21, 0xc3, 0xc6, 0xc3, 0xbb, 0x2b,
|
||||
0xd5, 0xda, 0x1d, 0xf1, 0xbc, 0xd1, 0xc2, 0xd5, 0xfd, 0x83, 0xe2, 0x25, 0xdd, 0xb6, 0x21, 0x3e,
|
||||
0xc5, 0x71, 0x28, 0x9b, 0xc0, 0xb7, 0x51, 0xf1, 0x04, 0xfb, 0x68, 0x01, 0xc9, 0x02, 0xd9, 0x3f,
|
||||
0x28, 0x5e, 0x39, 0xc6, 0x89, 0x5a, 0x47, 0x36, 0x81, 0xdf, 0x42, 0x17, 0x8f, 0xf7, 0x14, 0xd6,
|
||||
0xc5, 0x31, 0xf6, 0x73, 0x7f, 0x4c, 0xa0, 0x71, 0x35, 0xf5, 0xf8, 0xa6, 0x55, 0x28, 0xad, 0xf3,
|
||||
0x26, 0x51, 0xae, 0x34, 0x6b, 0xf5, 0x26, 0x48, 0xe1, 0xa6, 0x29, 0x5e, 0xcd, 0x85, 0x9f, 0x3c,
|
||||
0xc7, 0x35, 0xfa, 0x72, 0xa5, 0x56, 0xa1, 0xd5, 0xc5, 0x30, 0xa2, 0x8a, 0xbd, 0xcc, 0x1c, 0xe6,
|
||||
0xd9, 0x2d, 0xfc, 0x36, 0xba, 0x14, 0x77, 0xde, 0xb8, 0xb7, 0x78, 0x3b, 0xdc, 0x25, 0x58, 0xa0,
|
||||
0xf6, 0x80, 0xc6, 0x56, 0x6b, 0x13, 0x02, 0xf3, 0x4e, 0xcc, 0xaa, 0x5a, 0xbb, 0xbf, 0xb0, 0x52,
|
||||
0x2d, 0x0b, 0xab, 0x64, 0x21, 0xbf, 0x7f, 0x50, 0x3c, 0xaf, 0xac, 0xe4, 0x07, 0x0e, 0x6e, 0x36,
|
||||
0xf7, 0x4d, 0x02, 0xcd, 0x7c, 0xf7, 0xf0, 0xc2, 0x0f, 0xd0, 0xab, 0xb0, 0x5f, 0x47, 0x5a, 0x81,
|
||||
0xec, 0x5b, 0x62, 0x0f, 0x17, 0x56, 0x57, 0x2b, 0xb5, 0x72, 0x6e, 0xa4, 0x30, 0xbb, 0x7f, 0x50,
|
||||
0xbc, 0xf6, 0xdd, 0x2e, 0x17, 0x7a, 0x3d, 0xe6, 0x58, 0xa7, 0x74, 0xbc, 0x54, 0xa7, 0xcb, 0x95,
|
||||
0xb5, 0x5c, 0xe2, 0x34, 0x8e, 0x97, 0x5c, 0xaf, 0xcd, 0xfa, 0xa5, 0xbb, 0x4f, 0xbe, 0x9d, 0x19,
|
||||
0x79, 0xfa, 0xed, 0xcc, 0xc8, 0x93, 0x67, 0x33, 0x89, 0xa7, 0xcf, 0x66, 0x12, 0x3f, 0x7b, 0x3e,
|
||||
0x33, 0xf2, 0xd5, 0xf3, 0x99, 0xc4, 0xd3, 0xe7, 0x33, 0x23, 0x7f, 0x7a, 0x3e, 0x33, 0xf2, 0xe8,
|
||||
0xb5, 0xb6, 0xdd, 0xdf, 0xdc, 0x5a, 0xbf, 0xde, 0x72, 0xbb, 0x37, 0xfc, 0x3d, 0xa7, 0xd5, 0xdf,
|
||||
0xb4, 0x9d, 0xb6, 0xf6, 0x4b, 0xff, 0xcf, 0x0f, 0xeb, 0x19, 0xf8, 0xf5, 0xd6, 0x3f, 0x02, 0x00,
|
||||
0x00, 0xff, 0xff, 0x68, 0x4a, 0x6e, 0xeb, 0x13, 0x21, 0x00, 0x00,
|
||||
// 3183 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x5a, 0x4b, 0x6c, 0x1b, 0xc7,
|
||||
0xf9, 0x17, 0xc5, 0x87, 0xa8, 0xd1, 0xc3, 0xd4, 0xf8, 0xc5, 0xd0, 0xb6, 0x96, 0xff, 0x89, 0xf3,
|
||||
0xaf, 0xa2, 0x34, 0x76, 0xa2, 0x3c, 0x9a, 0xc6, 0xa9, 0x03, 0x51, 0xa4, 0x64, 0xc6, 0x32, 0xa9,
|
||||
0x0c, 0x65, 0x3b, 0x36, 0x50, 0x10, 0x2b, 0xee, 0x88, 0x5a, 0x98, 0xdc, 0x65, 0x77, 0xa9, 0x57,
|
||||
0xd0, 0x4b, 0x1b, 0x20, 0x08, 0x74, 0x28, 0x8a, 0x9c, 0x8a, 0x22, 0x42, 0x83, 0x5e, 0x7a, 0x2b,
|
||||
0xd0, 0x43, 0x2f, 0x39, 0xf5, 0xe8, 0xa3, 0x11, 0xa0, 0x40, 0xd1, 0xc3, 0x02, 0xb1, 0x2f, 0x2d,
|
||||
0x7b, 0xd3, 0xb1, 0xa7, 0x62, 0xbe, 0x99, 0x9d, 0x9d, 0xd5, 0x23, 0x95, 0x93, 0x43, 0x4f, 0xe6,
|
||||
0xf7, 0xfb, 0x7e, 0xdf, 0xb7, 0xb3, 0x33, 0xdf, 0x6b, 0x56, 0x46, 0x17, 0x3a, 0xf6, 0xda, 0xf5,
|
||||
0x9e, 0xe7, 0xf6, 0xdd, 0x96, 0xdb, 0xb9, 0xbe, 0xc6, 0x7a, 0xd7, 0x40, 0xc0, 0xd9, 0x10, 0x2b,
|
||||
0x8c, 0xb2, 0x9d, 0xbe, 0x00, 0x0b, 0x2f, 0x7a, 0xac, 0xe7, 0xfa, 0x82, 0xbe, 0xb6, 0xb9, 0x7e,
|
||||
0xbd, 0xed, 0xb6, 0x5d, 0x10, 0xe0, 0x97, 0x20, 0x91, 0xa7, 0x09, 0x94, 0xbe, 0xc5, 0x3a, 0x1d,
|
||||
0x17, 0x2f, 0xa0, 0x31, 0x8b, 0x6d, 0xd9, 0x2d, 0xd6, 0x74, 0xcc, 0x2e, 0xcb, 0x27, 0x8a, 0x89,
|
||||
0x99, 0xd1, 0x12, 0x19, 0x04, 0x06, 0x12, 0x70, 0xcd, 0xec, 0xb2, 0x83, 0xc0, 0xc8, 0xed, 0x74,
|
||||
0x3b, 0xef, 0x92, 0x08, 0x22, 0x54, 0xd3, 0x73, 0x27, 0xad, 0x8e, 0xcd, 0x9c, 0xbe, 0x70, 0x32,
|
||||
0x1c, 0x39, 0x11, 0x70, 0xcc, 0x49, 0x04, 0x11, 0xaa, 0xe9, 0x71, 0x1d, 0x4d, 0x4a, 0x27, 0x5b,
|
||||
0xcc, 0xf3, 0x6d, 0xd7, 0xc9, 0x27, 0xc1, 0xcf, 0xcc, 0x20, 0x30, 0x26, 0x84, 0xe6, 0x9e, 0x50,
|
||||
0x1c, 0x04, 0xc6, 0x59, 0xcd, 0x95, 0x44, 0x09, 0x8d, 0xb3, 0xc8, 0x9f, 0x12, 0x28, 0x73, 0x8b,
|
||||
0x99, 0x16, 0xf3, 0xf0, 0x3c, 0x4a, 0xf5, 0x77, 0x7b, 0xe2, 0xf5, 0x26, 0xe7, 0xce, 0x5f, 0x0b,
|
||||
0x37, 0xee, 0xda, 0x1d, 0xe6, 0xfb, 0x66, 0x9b, 0xad, 0xee, 0xf6, 0x58, 0xe9, 0xc2, 0x20, 0x30,
|
||||
0x80, 0x76, 0x10, 0x18, 0x08, 0xfc, 0x73, 0x81, 0x50, 0xc0, 0xb0, 0x85, 0xc6, 0x5a, 0x6e, 0xb7,
|
||||
0xe7, 0x31, 0x1f, 0xd6, 0x36, 0x0c, 0x9e, 0x2e, 0x1f, 0xf1, 0xb4, 0x10, 0x71, 0x4a, 0x57, 0x07,
|
||||
0x81, 0xa1, 0x1b, 0x1d, 0x04, 0xc6, 0x94, 0x58, 0x77, 0x84, 0x11, 0xaa, 0x33, 0xc8, 0x17, 0x09,
|
||||
0x34, 0xb1, 0xd0, 0xd9, 0xf4, 0xfb, 0xcc, 0x5b, 0x70, 0x9d, 0x75, 0xbb, 0x8d, 0x6f, 0xa3, 0x91,
|
||||
0x75, 0xb7, 0x63, 0x31, 0xcf, 0xcf, 0x27, 0x8a, 0xc9, 0x99, 0xb1, 0xb9, 0x5c, 0xf4, 0xcc, 0x45,
|
||||
0x50, 0x94, 0x8c, 0xc7, 0x81, 0x31, 0x34, 0x08, 0x8c, 0x90, 0x78, 0x10, 0x18, 0xe3, 0xf0, 0x1c,
|
||||
0x21, 0x13, 0x1a, 0x2a, 0xf0, 0x4d, 0x34, 0xea, 0xb3, 0x96, 0xeb, 0x58, 0xa6, 0xb7, 0x0b, 0xaf,
|
||||
0x90, 0x2d, 0x15, 0x07, 0x81, 0x11, 0x81, 0x07, 0x81, 0x71, 0x06, 0x4c, 0x15, 0x42, 0x68, 0xa4,
|
||||
0x25, 0x5f, 0xa5, 0x50, 0x46, 0x3c, 0x14, 0x5f, 0x43, 0xc3, 0xb6, 0x25, 0xe3, 0x65, 0xfa, 0x69,
|
||||
0x60, 0x0c, 0x57, 0xcb, 0x83, 0xc0, 0x18, 0xb6, 0xad, 0x83, 0xc0, 0xc8, 0x82, 0x0b, 0xdb, 0x22,
|
||||
0x9f, 0x3f, 0xb9, 0x3a, 0x5c, 0x2d, 0xd3, 0x61, 0xdb, 0xc2, 0xd7, 0x50, 0xba, 0x63, 0xae, 0xb1,
|
||||
0x8e, 0x8c, 0x8e, 0xfc, 0x20, 0x30, 0x04, 0x70, 0x10, 0x18, 0x63, 0xc0, 0x07, 0x89, 0x50, 0x81,
|
||||
0xe2, 0x1b, 0x68, 0xd4, 0x63, 0xa6, 0xd5, 0x74, 0x9d, 0xce, 0x2e, 0x44, 0x42, 0xb6, 0x34, 0x3d,
|
||||
0x08, 0x8c, 0x2c, 0x07, 0xeb, 0x4e, 0x87, 0xaf, 0x74, 0x12, 0xcc, 0x42, 0x80, 0x50, 0xa5, 0xc3,
|
||||
0x4d, 0x84, 0xed, 0xb6, 0xe3, 0x7a, 0xac, 0xd9, 0x63, 0x5e, 0xd7, 0x86, 0xbd, 0xf5, 0xf3, 0x29,
|
||||
0xf0, 0xf2, 0xda, 0x20, 0x30, 0xa6, 0x84, 0x76, 0x25, 0x52, 0x1e, 0x04, 0xc6, 0x45, 0xb1, 0xea,
|
||||
0xc3, 0x1a, 0x42, 0x8f, 0xb2, 0xf1, 0x6d, 0x34, 0x21, 0x1f, 0x60, 0xb1, 0x0e, 0xeb, 0xb3, 0x7c,
|
||||
0x1a, 0x7c, 0xff, 0xff, 0x20, 0x30, 0xc6, 0x85, 0xa2, 0x0c, 0xf8, 0x41, 0x60, 0x60, 0xcd, 0xad,
|
||||
0x00, 0x09, 0x8d, 0x71, 0xb0, 0x85, 0xce, 0x59, 0xb6, 0x6f, 0xae, 0x75, 0x58, 0xb3, 0xcf, 0xba,
|
||||
0xbd, 0xa6, 0xed, 0x58, 0x6c, 0x87, 0xf9, 0xf9, 0x0c, 0xf8, 0x9c, 0x1b, 0x04, 0x06, 0x96, 0xfa,
|
||||
0x55, 0xd6, 0xed, 0x55, 0x85, 0xf6, 0x20, 0x30, 0xf2, 0x22, 0x29, 0x8f, 0xa8, 0x08, 0x3d, 0x86,
|
||||
0x8f, 0xe7, 0x50, 0xa6, 0x67, 0x6e, 0xfa, 0xcc, 0xca, 0x8f, 0x80, 0xdf, 0xc2, 0x20, 0x30, 0x24,
|
||||
0xa2, 0x02, 0x46, 0x88, 0x84, 0x4a, 0x9c, 0x07, 0x9f, 0x48, 0x73, 0x3f, 0x9f, 0x3b, 0x1c, 0x7c,
|
||||
0x65, 0x50, 0x44, 0xc1, 0x27, 0x89, 0xca, 0x97, 0x90, 0x09, 0x0d, 0x15, 0xe4, 0x2f, 0x19, 0x94,
|
||||
0x11, 0x46, 0xb8, 0xa4, 0x82, 0x67, 0xbc, 0x34, 0xc7, 0x1d, 0xfc, 0x3d, 0x30, 0xb2, 0x42, 0x57,
|
||||
0x2d, 0x9f, 0x14, 0x4c, 0x9f, 0x3d, 0xb9, 0x9a, 0xd0, 0x02, 0x6a, 0x16, 0xa5, 0xb4, 0x6a, 0x03,
|
||||
0xc9, 0xeb, 0x88, 0x3a, 0x23, 0x92, 0xd7, 0x81, 0x0a, 0x03, 0x18, 0x7e, 0x0f, 0x8d, 0x9a, 0x96,
|
||||
0xc5, 0x93, 0x8c, 0xf9, 0xf9, 0x64, 0x31, 0xc9, 0x63, 0x96, 0xc7, 0xbd, 0x02, 0x0f, 0x02, 0x63,
|
||||
0x02, 0xac, 0x24, 0x42, 0x68, 0xa4, 0xc3, 0x3f, 0x8d, 0xa7, 0x7e, 0xea, 0x70, 0x11, 0xf9, 0x7e,
|
||||
0x39, 0xcf, 0x23, 0xbd, 0xc5, 0x3c, 0x59, 0x3b, 0xd3, 0x22, 0xa1, 0x78, 0xa4, 0x73, 0x50, 0x56,
|
||||
0x4e, 0x11, 0xe9, 0x21, 0x40, 0xa8, 0xd2, 0xe1, 0x25, 0x34, 0xde, 0x35, 0x77, 0x9a, 0x3e, 0xfb,
|
||||
0xd9, 0x26, 0x73, 0x5a, 0x0c, 0x62, 0x26, 0x29, 0x56, 0xd1, 0x35, 0x77, 0x1a, 0x12, 0x56, 0xab,
|
||||
0xd0, 0x30, 0x42, 0x75, 0x06, 0x2e, 0x21, 0x64, 0x3b, 0x7d, 0xcf, 0xb5, 0x36, 0x5b, 0xcc, 0x93,
|
||||
0x21, 0x02, 0x25, 0x3c, 0x42, 0x55, 0x09, 0x8f, 0x20, 0x42, 0x35, 0x3d, 0x6e, 0xa3, 0x2c, 0xc4,
|
||||
0x6e, 0xd3, 0xb6, 0xf2, 0xd9, 0x62, 0x62, 0x26, 0x55, 0x5a, 0x96, 0x87, 0x3b, 0x02, 0x51, 0x08,
|
||||
0x67, 0x1b, 0xfe, 0xe4, 0x31, 0x03, 0xec, 0xaa, 0xa5, 0x76, 0x5f, 0xca, 0xbc, 0x6e, 0x84, 0xb4,
|
||||
0xdf, 0x46, 0x3f, 0x69, 0xc8, 0xc7, 0x3f, 0x47, 0x05, 0xff, 0x91, 0xcd, 0x33, 0x45, 0x3c, 0xbb,
|
||||
0x6f, 0xbb, 0x4e, 0xd3, 0x63, 0x5d, 0x77, 0xcb, 0xec, 0xf8, 0xf9, 0x51, 0x58, 0xfc, 0xcd, 0x41,
|
||||
0x60, 0xe4, 0x39, 0xab, 0xaa, 0x91, 0xa8, 0xe4, 0x1c, 0x04, 0xc6, 0xb4, 0xa8, 0x73, 0x27, 0x10,
|
||||
0x08, 0x3d, 0xd1, 0x16, 0xef, 0xa0, 0x17, 0x98, 0xd3, 0xf2, 0x76, 0x7b, 0xf0, 0xd8, 0x9e, 0xe9,
|
||||
0xfb, 0xdb, 0xae, 0x67, 0x35, 0xfb, 0xee, 0x23, 0xe6, 0xe4, 0x11, 0x04, 0xf5, 0x7b, 0x83, 0xc0,
|
||||
0xb8, 0x18, 0x91, 0x56, 0x24, 0x67, 0x95, 0x53, 0x0e, 0x02, 0xe3, 0x0a, 0x3c, 0xfb, 0x04, 0x3d,
|
||||
0xa1, 0x27, 0x59, 0x92, 0x5f, 0x26, 0x50, 0x1a, 0x36, 0x83, 0x67, 0xb3, 0x28, 0xea, 0xb2, 0x04,
|
||||
0x43, 0x36, 0x0b, 0xe4, 0x48, 0xf9, 0x97, 0x38, 0xae, 0xa0, 0xf4, 0xba, 0xdd, 0x61, 0x7e, 0x7e,
|
||||
0x18, 0x72, 0x19, 0x6b, 0x8d, 0xc4, 0xee, 0xb0, 0xaa, 0xb3, 0xee, 0x96, 0x2e, 0xc9, 0x6c, 0x16,
|
||||
0x44, 0x95, 0x4b, 0x5c, 0x22, 0x54, 0x80, 0xe4, 0xb3, 0x04, 0x1a, 0x83, 0x45, 0xdc, 0xed, 0x59,
|
||||
0x66, 0x9f, 0xfd, 0x2f, 0x97, 0xf2, 0xe9, 0x04, 0xca, 0x86, 0x06, 0xaa, 0x20, 0x24, 0x4e, 0x51,
|
||||
0x10, 0x66, 0x51, 0xca, 0xb7, 0x3f, 0x66, 0xd0, 0x58, 0x92, 0x82, 0xcb, 0x65, 0xc5, 0xe5, 0x02,
|
||||
0xa1, 0x80, 0xe1, 0xf7, 0x11, 0xea, 0xba, 0x96, 0xbd, 0x6e, 0x33, 0xab, 0xe9, 0x43, 0x82, 0x26,
|
||||
0x45, 0xd7, 0x0c, 0xd1, 0x86, 0xea, 0x9a, 0x0a, 0x21, 0x34, 0xd2, 0xf2, 0xfa, 0xa1, 0x1c, 0xac,
|
||||
0xed, 0xe6, 0xc7, 0x21, 0x33, 0xde, 0x0b, 0x33, 0xa3, 0xb1, 0xe1, 0x7a, 0x7d, 0x48, 0x07, 0xf5,
|
||||
0x98, 0xd2, 0xae, 0x4a, 0xb5, 0x08, 0x22, 0x3c, 0x13, 0x24, 0x99, 0x6a, 0x54, 0xbc, 0x8c, 0x46,
|
||||
0xc2, 0x89, 0x89, 0x47, 0x7e, 0xac, 0x48, 0xdf, 0x63, 0xad, 0xbe, 0xeb, 0x95, 0x8a, 0x61, 0x91,
|
||||
0xde, 0x52, 0x13, 0x94, 0x48, 0xb8, 0xad, 0x70, 0x76, 0x0a, 0x35, 0xf8, 0x5d, 0x94, 0x55, 0xc5,
|
||||
0x04, 0xc1, 0xbb, 0x42, 0x31, 0xf2, 0xa3, 0x4a, 0x32, 0x29, 0x07, 0x84, 0xb0, 0x8c, 0x28, 0x1d,
|
||||
0xfe, 0x00, 0x65, 0xd6, 0x3a, 0x6e, 0xeb, 0x51, 0xd8, 0x2d, 0xce, 0x46, 0x0b, 0x29, 0x71, 0x1c,
|
||||
0xce, 0xf5, 0x8a, 0x5c, 0x8b, 0xa4, 0xaa, 0xf6, 0x0f, 0x22, 0xa1, 0x12, 0xe6, 0xe3, 0xa0, 0xbf,
|
||||
0xdb, 0xed, 0xd8, 0xce, 0xa3, 0x66, 0xdf, 0xf4, 0xda, 0xac, 0x9f, 0x9f, 0x8a, 0xc6, 0x41, 0xa9,
|
||||
0x59, 0x05, 0x85, 0x1a, 0x07, 0x63, 0x28, 0xa1, 0x71, 0x16, 0x1f, 0x52, 0x85, 0xeb, 0xe6, 0x86,
|
||||
0xe9, 0x6f, 0xe4, 0x31, 0xe4, 0x29, 0x54, 0x38, 0x01, 0xdf, 0x32, 0xfd, 0x0d, 0xb5, 0xed, 0x11,
|
||||
0x44, 0xa8, 0xa6, 0xe7, 0x03, 0x94, 0xcc, 0x4d, 0x66, 0xe5, 0xcf, 0x82, 0x0b, 0x08, 0x05, 0x05,
|
||||
0xaa, 0x50, 0x50, 0x08, 0xa1, 0x91, 0x16, 0x97, 0xe4, 0x20, 0x2a, 0xc6, 0xc7, 0x0b, 0x47, 0xc3,
|
||||
0xfe, 0x14, 0x93, 0xe8, 0x22, 0x1a, 0x3b, 0x3c, 0xd5, 0x4c, 0x88, 0x8a, 0xdf, 0x8b, 0xcd, 0x33,
|
||||
0xa2, 0xe2, 0xf7, 0xf4, 0x49, 0x46, 0x67, 0xe0, 0x0f, 0xb4, 0xb0, 0x74, 0xfc, 0xfc, 0x58, 0x31,
|
||||
0x31, 0x93, 0x2e, 0xbd, 0xac, 0xc7, 0x61, 0xcd, 0x3f, 0x12, 0x87, 0x35, 0x9f, 0xfc, 0x3b, 0x30,
|
||||
0x92, 0xb6, 0xd3, 0xa7, 0x1a, 0x0d, 0xaf, 0x23, 0xb1, 0x4b, 0x4d, 0xc8, 0xaa, 0x09, 0x70, 0xb5,
|
||||
0xf4, 0x34, 0x30, 0xc6, 0xa9, 0xb9, 0x0d, 0x47, 0xdf, 0xb0, 0x3f, 0x66, 0x7c, 0xa3, 0xd6, 0x42,
|
||||
0x41, 0x6d, 0x94, 0x42, 0x42, 0xc7, 0x9f, 0x3f, 0xb9, 0x1a, 0x33, 0xa3, 0x91, 0x11, 0xbe, 0x87,
|
||||
0xb2, 0xbd, 0x8e, 0xd9, 0x5f, 0x77, 0xbd, 0x6e, 0x7e, 0x12, 0x82, 0x5d, 0xdb, 0xc3, 0x15, 0xa9,
|
||||
0x29, 0x9b, 0x7d, 0xb3, 0x44, 0x64, 0x98, 0x29, 0xbe, 0x8a, 0xdc, 0x10, 0x20, 0x54, 0xe9, 0x70,
|
||||
0x19, 0x8d, 0x75, 0xdc, 0x96, 0xd9, 0x69, 0xae, 0x77, 0xcc, 0xb6, 0x9f, 0xff, 0xc7, 0x08, 0x6c,
|
||||
0x2a, 0x44, 0x07, 0xe0, 0x8b, 0x1c, 0x56, 0x9b, 0x11, 0x41, 0x84, 0x6a, 0x7a, 0x7c, 0x0b, 0x8d,
|
||||
0xcb, 0x34, 0x12, 0x31, 0xf6, 0xcf, 0x11, 0x88, 0x10, 0x38, 0x1b, 0xa9, 0x90, 0x51, 0x36, 0xa5,
|
||||
0x67, 0x9f, 0x08, 0x33, 0x9d, 0x81, 0x3f, 0x44, 0x67, 0x6c, 0xc7, 0xb5, 0x58, 0xb3, 0xb5, 0x61,
|
||||
0x3a, 0x6d, 0xc6, 0xcf, 0x67, 0x30, 0x02, 0xd9, 0x08, 0xf1, 0x0f, 0xba, 0x05, 0x50, 0xc1, 0x19,
|
||||
0x9d, 0x95, 0xdd, 0x53, 0x43, 0x09, 0x8d, 0xb3, 0xf0, 0x0e, 0xd2, 0xda, 0x4a, 0xb3, 0xef, 0x99,
|
||||
0x76, 0x87, 0x79, 0xe2, 0xbc, 0xfe, 0x35, 0x02, 0x07, 0xf6, 0xfe, 0x20, 0x30, 0xce, 0x47, 0x9c,
|
||||
0x55, 0x41, 0x91, 0x87, 0x75, 0xe9, 0x50, 0xcb, 0xd2, 0xb4, 0x2a, 0x22, 0x8e, 0x37, 0xc6, 0x6f,
|
||||
0xf3, 0x29, 0x92, 0x4f, 0xba, 0x96, 0x1c, 0x69, 0x2f, 0x8b, 0x79, 0x11, 0x20, 0x55, 0x8a, 0xa4,
|
||||
0x0c, 0x03, 0x23, 0xfc, 0xc2, 0x14, 0x8d, 0xd8, 0xce, 0x96, 0xd9, 0xb1, 0xc3, 0x91, 0xf5, 0x9d,
|
||||
0xa7, 0x81, 0x81, 0xa8, 0xb9, 0x5d, 0x15, 0xa8, 0x98, 0x20, 0xe0, 0xa7, 0x36, 0x41, 0x80, 0xcc,
|
||||
0x27, 0x08, 0x8d, 0x49, 0x43, 0x1e, 0x2f, 0x2b, 0x8e, 0x1b, 0xbb, 0x15, 0x64, 0xc1, 0x35, 0x6c,
|
||||
0xab, 0xe3, 0xc6, 0x6f, 0x04, 0x62, 0x5b, 0x63, 0x28, 0xa1, 0x71, 0xd6, 0xbb, 0xa9, 0xdf, 0x7c,
|
||||
0x69, 0x0c, 0x91, 0x6f, 0x12, 0x68, 0x54, 0x95, 0x38, 0xde, 0x5d, 0xe0, 0xfc, 0x93, 0x70, 0xfc,
|
||||
0x90, 0xcd, 0x1b, 0xe2, 0xdc, 0x45, 0x36, 0x6f, 0xc0, 0x81, 0x03, 0xc6, 0xbb, 0xa7, 0xbb, 0xbe,
|
||||
0xee, 0xb3, 0x3e, 0xf4, 0xad, 0xa4, 0xe8, 0x9e, 0x02, 0x51, 0xdd, 0x53, 0x88, 0x84, 0x4a, 0x1c,
|
||||
0xbf, 0x2e, 0xbb, 0xd7, 0x30, 0x1c, 0xdb, 0x95, 0xe3, 0xbb, 0x57, 0x78, 0x28, 0xa2, 0x89, 0xdd,
|
||||
0x40, 0xa3, 0xdb, 0xcc, 0x7c, 0x24, 0xe2, 0x52, 0x94, 0x0c, 0xa8, 0xeb, 0x1c, 0x94, 0x31, 0x29,
|
||||
0xb2, 0x23, 0x04, 0x08, 0x55, 0x3a, 0xf9, 0x8e, 0x0f, 0x51, 0x46, 0xb4, 0x13, 0xbc, 0x82, 0xb2,
|
||||
0x2d, 0x77, 0xd3, 0xe9, 0x47, 0x97, 0xd2, 0x29, 0x7d, 0x1a, 0x06, 0x4d, 0xe9, 0xff, 0xc2, 0x04,
|
||||
0x0c, 0xa9, 0xea, 0x8c, 0x24, 0xc0, 0xc7, 0x58, 0xa9, 0x22, 0x9f, 0x24, 0xd0, 0x88, 0x34, 0xc4,
|
||||
0xb7, 0xd4, 0xe5, 0x20, 0x55, 0x7a, 0xe7, 0x50, 0x97, 0xfc, 0xf6, 0x8b, 0xa6, 0xde, 0x21, 0xe5,
|
||||
0x9d, 0x73, 0xcb, 0xec, 0x6c, 0x8a, 0x8d, 0x4a, 0x89, 0x3b, 0x27, 0x00, 0xaa, 0xe9, 0x80, 0x44,
|
||||
0xa8, 0x40, 0xc9, 0x27, 0x29, 0x34, 0xae, 0x17, 0x11, 0x5e, 0xae, 0x37, 0x1d, 0x7b, 0x07, 0x16,
|
||||
0x13, 0x9b, 0x52, 0xee, 0x3a, 0xf6, 0x0e, 0x94, 0x99, 0xc2, 0xe3, 0xc0, 0x48, 0xf0, 0x03, 0xe0,
|
||||
0x3c, 0x75, 0x00, 0x5c, 0x20, 0x14, 0x30, 0xfc, 0x21, 0x1a, 0xd9, 0xb6, 0x1d, 0xcb, 0xdd, 0xf6,
|
||||
0x61, 0x19, 0x63, 0xfa, 0xcd, 0xe1, 0xbe, 0x50, 0x80, 0xa7, 0xa2, 0xf4, 0x14, 0xb2, 0xd5, 0x76,
|
||||
0x49, 0x99, 0xd0, 0x50, 0x83, 0x97, 0x50, 0xba, 0x63, 0x3b, 0x9b, 0x3b, 0x10, 0x60, 0xb1, 0x36,
|
||||
0xfb, 0x91, 0xd9, 0xef, 0x7b, 0xe0, 0xee, 0xb2, 0x74, 0x27, 0x98, 0xd1, 0x25, 0x9b, 0x4b, 0xfc,
|
||||
0x92, 0xcd, 0xff, 0xc5, 0xb7, 0x51, 0xc6, 0x32, 0xbd, 0x6d, 0x5b, 0x5c, 0x6a, 0x4e, 0xf0, 0x34,
|
||||
0x2d, 0x3d, 0x49, 0x6a, 0x74, 0xc1, 0x03, 0x91, 0x50, 0x89, 0x63, 0x86, 0x46, 0xd6, 0x3d, 0xc6,
|
||||
0xd6, 0x7c, 0x0b, 0x86, 0xa4, 0x13, 0xbc, 0xbd, 0xcd, 0xbd, 0xf1, 0x6b, 0xc0, 0xa2, 0xc7, 0x58,
|
||||
0xa9, 0x01, 0xd7, 0x00, 0x69, 0xa6, 0xde, 0x58, 0xca, 0x70, 0x0d, 0x90, 0x34, 0x1a, 0x92, 0x70,
|
||||
0x13, 0x65, 0x1c, 0xd6, 0xe7, 0x4f, 0xc9, 0x9c, 0xfc, 0x94, 0x39, 0xf9, 0x94, 0x4c, 0x8d, 0xf5,
|
||||
0xc5, 0x43, 0xa4, 0x91, 0x5a, 0xbd, 0x10, 0xf9, 0x23, 0x24, 0x87, 0x4a, 0x06, 0xf9, 0x74, 0x18,
|
||||
0x65, 0xc3, 0xf3, 0xe5, 0xc3, 0x9f, 0xbb, 0xed, 0x30, 0x4f, 0xff, 0x3c, 0x06, 0x1d, 0x1f, 0x50,
|
||||
0x79, 0x3d, 0x13, 0x8d, 0x4c, 0x21, 0x84, 0x46, 0x5a, 0xee, 0xa0, 0xed, 0xb9, 0x9b, 0x3d, 0xfd,
|
||||
0xd3, 0x18, 0x38, 0x00, 0x34, 0xe6, 0x40, 0x21, 0x84, 0x46, 0x5a, 0x7c, 0x03, 0x25, 0x37, 0x6d,
|
||||
0x0b, 0x8e, 0x3a, 0x5d, 0x7a, 0xf9, 0x69, 0x60, 0x24, 0xef, 0x42, 0x06, 0x70, 0xf4, 0x20, 0x30,
|
||||
0x46, 0x45, 0xc0, 0xd9, 0x96, 0xd6, 0x3e, 0x39, 0x83, 0x72, 0x3d, 0x37, 0x6e, 0xdb, 0x16, 0x9c,
|
||||
0xae, 0x34, 0x5e, 0x12, 0xc6, 0x6d, 0xcd, 0xb8, 0x1d, 0x37, 0x5e, 0xe2, 0xc6, 0x1c, 0xfb, 0x22,
|
||||
0x81, 0xc6, 0xb4, 0x08, 0xfd, 0xfe, 0x7b, 0xb1, 0x8c, 0x26, 0x85, 0x03, 0xdb, 0x6f, 0xc2, 0x0b,
|
||||
0xca, 0x6f, 0x50, 0xf0, 0xd9, 0x04, 0x34, 0x55, 0x7f, 0x89, 0xe3, 0xea, 0xb3, 0x89, 0x0e, 0x12,
|
||||
0x1a, 0xe3, 0x90, 0x06, 0x1a, 0x55, 0x07, 0x8e, 0x17, 0x51, 0x66, 0x87, 0x0b, 0x61, 0x41, 0x3a,
|
||||
0x73, 0x28, 0x2a, 0xa2, 0xb1, 0x53, 0xd0, 0x54, 0x42, 0x80, 0x48, 0xa8, 0x84, 0x49, 0x0b, 0xa5,
|
||||
0x81, 0xff, 0x5c, 0xb7, 0x89, 0x58, 0x9d, 0x19, 0xff, 0xef, 0x75, 0xe6, 0x17, 0x29, 0x34, 0x42,
|
||||
0xf9, 0xd0, 0xec, 0xf7, 0xf1, 0x5b, 0xaa, 0xda, 0xa5, 0x4b, 0x2f, 0x9d, 0x54, 0xde, 0xa2, 0xd3,
|
||||
0x09, 0xbf, 0x7e, 0x44, 0x97, 0xae, 0xe1, 0x53, 0x5f, 0xba, 0xc2, 0x57, 0x4a, 0x9e, 0xe2, 0x95,
|
||||
0xa2, 0xb6, 0x94, 0x7a, 0xee, 0xb6, 0x94, 0x3e, 0x7d, 0x5b, 0x0a, 0x3b, 0x65, 0xe6, 0x14, 0x9d,
|
||||
0xb2, 0x8e, 0x26, 0xd7, 0x3d, 0xb7, 0x0b, 0xdf, 0xc8, 0x5c, 0xcf, 0xf4, 0x76, 0xe5, 0x54, 0x00,
|
||||
0xad, 0x9b, 0x6b, 0x56, 0x43, 0x85, 0x6a, 0xdd, 0x31, 0x94, 0xd0, 0x38, 0x2b, 0xde, 0x13, 0xb3,
|
||||
0xcf, 0xd7, 0x13, 0xf1, 0x4d, 0x94, 0x15, 0x13, 0xaf, 0xe3, 0xc2, 0xb5, 0x2b, 0x5d, 0x7a, 0x91,
|
||||
0x97, 0x32, 0xc0, 0x6a, 0xae, 0x2a, 0x65, 0x52, 0x56, 0xaf, 0x1d, 0x12, 0xc8, 0x1f, 0x13, 0x28,
|
||||
0x4b, 0x99, 0xdf, 0x73, 0x1d, 0x9f, 0x7d, 0xd7, 0x20, 0x98, 0x45, 0x29, 0xcb, 0xec, 0x9b, 0x32,
|
||||
0xec, 0x60, 0xf7, 0xb8, 0xac, 0x76, 0x8f, 0x0b, 0x84, 0x02, 0x86, 0xdf, 0x47, 0xa9, 0x96, 0x6b,
|
||||
0x89, 0xc3, 0x9f, 0xd4, 0x8b, 0x66, 0xc5, 0xf3, 0x5c, 0x6f, 0xc1, 0xb5, 0xe4, 0xb5, 0x83, 0x93,
|
||||
0x94, 0x03, 0x2e, 0x10, 0x0a, 0x18, 0xf9, 0x43, 0x02, 0xe5, 0xca, 0xee, 0xb6, 0xd3, 0x71, 0x4d,
|
||||
0x6b, 0xc5, 0x73, 0xdb, 0x1e, 0xf3, 0xfd, 0xef, 0x74, 0xf7, 0x6f, 0xa2, 0x91, 0x4d, 0xf8, 0x72,
|
||||
0x10, 0xde, 0xfe, 0xaf, 0xc6, 0xaf, 0x41, 0x87, 0x1f, 0x22, 0x3e, 0x33, 0x44, 0x1f, 0x1a, 0xa5,
|
||||
0xb1, 0xf2, 0x2f, 0x64, 0x42, 0x43, 0x05, 0xf9, 0x7d, 0x12, 0x15, 0x4e, 0x76, 0x84, 0xbb, 0x68,
|
||||
0x4c, 0x30, 0x9b, 0xda, 0xdf, 0x04, 0x66, 0x4e, 0xb3, 0x06, 0xb8, 0x9c, 0xc1, 0xa5, 0x60, 0x53,
|
||||
0xc9, 0xea, 0x52, 0x10, 0x41, 0x84, 0x6a, 0xfa, 0xe7, 0xfa, 0x4e, 0xa9, 0x5d, 0xe5, 0x93, 0xdf,
|
||||
0xff, 0x2a, 0xdf, 0x40, 0x13, 0x22, 0x44, 0xc3, 0x0f, 0xca, 0xa9, 0x62, 0x72, 0x26, 0x5d, 0xba,
|
||||
0xc6, 0xab, 0xed, 0x9a, 0x18, 0x56, 0xc3, 0x4f, 0xc9, 0x53, 0x51, 0xb0, 0x0a, 0x30, 0x8c, 0xb6,
|
||||
0xdc, 0x10, 0x8d, 0x71, 0xf1, 0x62, 0xec, 0xa6, 0x27, 0x52, 0xfd, 0x07, 0xa7, 0xbc, 0xd9, 0x69,
|
||||
0x37, 0x39, 0x92, 0x41, 0xa9, 0x15, 0xdb, 0x69, 0x93, 0x1b, 0x28, 0xbd, 0xd0, 0x71, 0x7d, 0xa8,
|
||||
0x38, 0x1e, 0x33, 0x7d, 0xd7, 0xd1, 0x43, 0x49, 0x20, 0xea, 0xa8, 0x85, 0x48, 0xa8, 0xc4, 0x67,
|
||||
0xbf, 0x4a, 0xa2, 0x31, 0xed, 0x4f, 0x38, 0xf8, 0x27, 0xe8, 0xd2, 0x9d, 0x4a, 0xa3, 0x31, 0xbf,
|
||||
0x54, 0x69, 0xae, 0x3e, 0x58, 0xa9, 0x34, 0x17, 0x96, 0xef, 0x36, 0x56, 0x2b, 0xb4, 0xb9, 0x50,
|
||||
0xaf, 0x2d, 0x56, 0x97, 0x72, 0x43, 0x85, 0xcb, 0x7b, 0xfb, 0xc5, 0xbc, 0x66, 0x11, 0xff, 0x5b,
|
||||
0xcb, 0x0f, 0x11, 0x8e, 0x99, 0x57, 0x6b, 0xe5, 0xca, 0x47, 0xb9, 0x44, 0xe1, 0xdc, 0xde, 0x7e,
|
||||
0x31, 0xa7, 0x59, 0x89, 0x4f, 0x70, 0x3f, 0x46, 0x2f, 0x1c, 0x65, 0x37, 0xef, 0xae, 0x94, 0xe7,
|
||||
0x57, 0x2b, 0xb9, 0xe1, 0x42, 0x61, 0x6f, 0xbf, 0x78, 0xe1, 0xb0, 0x91, 0x0c, 0xc1, 0xd7, 0xd0,
|
||||
0xb9, 0x98, 0x29, 0xad, 0x7c, 0x78, 0xb7, 0xd2, 0x58, 0xcd, 0x25, 0x0b, 0x17, 0xf6, 0xf6, 0x8b,
|
||||
0x58, 0xb3, 0x0a, 0xdb, 0xc4, 0x1c, 0x3a, 0x7f, 0xc8, 0xa2, 0xb1, 0x52, 0xaf, 0x35, 0x2a, 0xb9,
|
||||
0x54, 0xe1, 0xe2, 0xde, 0x7e, 0xf1, 0x6c, 0xcc, 0x44, 0x56, 0x95, 0x05, 0x34, 0x1d, 0xb3, 0x29,
|
||||
0xd7, 0xef, 0xd7, 0x96, 0xeb, 0xf3, 0xe5, 0xe6, 0x0a, 0xad, 0x2f, 0xd1, 0x4a, 0xa3, 0x91, 0x4b,
|
||||
0x17, 0x8c, 0xbd, 0xfd, 0xe2, 0x25, 0xcd, 0xf8, 0x48, 0x86, 0xcf, 0xa2, 0xa9, 0x98, 0x93, 0x95,
|
||||
0x6a, 0x6d, 0x29, 0x97, 0x29, 0x9c, 0xdd, 0xdb, 0x2f, 0x9e, 0xd1, 0xec, 0xf8, 0x59, 0x1e, 0xd9,
|
||||
0xbf, 0x85, 0xe5, 0x7a, 0xa3, 0x92, 0x1b, 0x39, 0xb2, 0x7f, 0x70, 0xe0, 0xb3, 0xbf, 0x4b, 0x20,
|
||||
0x7c, 0xf4, 0xaf, 0x66, 0xf8, 0x1d, 0x94, 0x0f, 0x9d, 0x2c, 0xd4, 0xef, 0xac, 0xf0, 0x75, 0x56,
|
||||
0xeb, 0xb5, 0x66, 0xad, 0x5e, 0xab, 0xe4, 0x86, 0x62, 0xbb, 0xaa, 0x59, 0xd5, 0x5c, 0x87, 0xe1,
|
||||
0x3a, 0xba, 0x78, 0x9c, 0xe5, 0xf2, 0xc3, 0x37, 0x73, 0x89, 0xc2, 0xdc, 0xde, 0x7e, 0xf1, 0xfc,
|
||||
0x51, 0xc3, 0xe5, 0x87, 0x6f, 0x7e, 0xfd, 0xab, 0x97, 0x8e, 0x57, 0xcc, 0xf2, 0x01, 0x48, 0x5f,
|
||||
0xda, 0xeb, 0xe8, 0x9c, 0xee, 0xf8, 0x4e, 0x65, 0x75, 0xbe, 0x3c, 0xbf, 0x3a, 0x9f, 0x1b, 0x12,
|
||||
0x67, 0xa0, 0x51, 0xef, 0xb0, 0xbe, 0x09, 0x65, 0xf7, 0x15, 0x34, 0x15, 0x7b, 0x8b, 0xca, 0xbd,
|
||||
0x0a, 0x0d, 0x23, 0x4a, 0x5f, 0x3f, 0xdb, 0x62, 0x1e, 0x7e, 0x15, 0x61, 0x9d, 0x3c, 0xbf, 0x7c,
|
||||
0x7f, 0xfe, 0x41, 0x23, 0x37, 0x5c, 0x38, 0xbf, 0xb7, 0x5f, 0x9c, 0xd2, 0xd8, 0xf3, 0x9d, 0x6d,
|
||||
0x73, 0xd7, 0x9f, 0xfd, 0xf3, 0x30, 0x1a, 0xd7, 0xbf, 0x1b, 0xe1, 0x57, 0xd1, 0xd9, 0xc5, 0xea,
|
||||
0x32, 0x8f, 0xc4, 0xc5, 0xba, 0x38, 0x01, 0x2e, 0xe6, 0x86, 0xc4, 0xe3, 0x74, 0x2a, 0xff, 0x8d,
|
||||
0x7f, 0x84, 0xf2, 0x87, 0xe8, 0xe5, 0x2a, 0xad, 0x2c, 0xac, 0xd6, 0xe9, 0x83, 0x5c, 0xa2, 0xf0,
|
||||
0x02, 0xdf, 0x30, 0xdd, 0xa6, 0x6c, 0x7b, 0x50, 0x82, 0x76, 0xf1, 0x4d, 0x74, 0xe9, 0x90, 0x61,
|
||||
0xe3, 0xc1, 0x9d, 0xe5, 0x6a, 0xed, 0xb6, 0x78, 0xde, 0x70, 0xe1, 0xca, 0xde, 0x7e, 0xf1, 0xa2,
|
||||
0x6e, 0xdb, 0x10, 0x9f, 0xe2, 0x38, 0x94, 0x4d, 0xe0, 0x5b, 0xa8, 0x78, 0x82, 0x7d, 0xb4, 0x80,
|
||||
0x64, 0x81, 0xec, 0xed, 0x17, 0x2f, 0x1f, 0xe3, 0x44, 0xad, 0x23, 0x9b, 0xc0, 0x6f, 0xa0, 0x0b,
|
||||
0xc7, 0x7b, 0x0a, 0xf3, 0xe2, 0x18, 0xfb, 0xd9, 0xbf, 0x26, 0xd0, 0xa8, 0xea, 0x7a, 0x7c, 0xd3,
|
||||
0x2a, 0x94, 0xd6, 0x79, 0x91, 0x28, 0x57, 0x9a, 0xb5, 0x7a, 0x13, 0xa4, 0x70, 0xd3, 0x14, 0xaf,
|
||||
0xe6, 0xc2, 0x4f, 0x1e, 0xe3, 0x1a, 0x7d, 0xa9, 0x52, 0xab, 0xd0, 0xea, 0x42, 0x78, 0xa2, 0x8a,
|
||||
0xbd, 0xc4, 0x1c, 0xe6, 0xd9, 0x2d, 0xfc, 0x26, 0xba, 0x18, 0x77, 0xde, 0xb8, 0xbb, 0x70, 0x2b,
|
||||
0xdc, 0x25, 0x58, 0xa0, 0xf6, 0x80, 0xc6, 0x66, 0x6b, 0x03, 0x0e, 0xe6, 0xad, 0x98, 0x55, 0xb5,
|
||||
0x76, 0x6f, 0x7e, 0xb9, 0x5a, 0x16, 0x56, 0xc9, 0x42, 0x7e, 0x6f, 0xbf, 0x78, 0x4e, 0x59, 0xc9,
|
||||
0x0f, 0x1c, 0xdc, 0x6c, 0xf6, 0xeb, 0x04, 0x9a, 0xfe, 0xf6, 0xe6, 0x85, 0xef, 0xa3, 0x97, 0x61,
|
||||
0xbf, 0x8e, 0x94, 0x02, 0x59, 0xb7, 0xc4, 0x1e, 0xce, 0xaf, 0xac, 0x54, 0x6a, 0xe5, 0xdc, 0x50,
|
||||
0x61, 0x66, 0x6f, 0xbf, 0x78, 0xf5, 0xdb, 0x5d, 0xce, 0xf7, 0x7a, 0xcc, 0xb1, 0x4e, 0xe9, 0x78,
|
||||
0xb1, 0x4e, 0x97, 0x2a, 0xab, 0xb9, 0xc4, 0x69, 0x1c, 0x2f, 0xba, 0x5e, 0x9b, 0xf5, 0x4b, 0x77,
|
||||
0x1e, 0x7f, 0x33, 0x3d, 0xf4, 0xe4, 0x9b, 0xe9, 0xa1, 0xc7, 0x4f, 0xa7, 0x13, 0x4f, 0x9e, 0x4e,
|
||||
0x27, 0x7e, 0xfd, 0x6c, 0x7a, 0xe8, 0xcb, 0x67, 0xd3, 0x89, 0x27, 0xcf, 0xa6, 0x87, 0xfe, 0xf6,
|
||||
0x6c, 0x7a, 0xe8, 0xe1, 0x2b, 0x6d, 0xbb, 0xbf, 0xb1, 0xb9, 0x76, 0xad, 0xe5, 0x76, 0xaf, 0xfb,
|
||||
0xbb, 0x4e, 0xab, 0xbf, 0x61, 0x3b, 0x6d, 0xed, 0x97, 0xfe, 0xbf, 0x27, 0xd6, 0x32, 0xf0, 0xeb,
|
||||
0x8d, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xa2, 0xde, 0xa7, 0x53, 0x54, 0x21, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Hello) Marshal() (dAtA []byte, err error) {
|
||||
@ -1440,6 +1442,16 @@ func (m *ClusterConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Secondary {
|
||||
i--
|
||||
if m.Secondary {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x10
|
||||
}
|
||||
if len(m.Folders) > 0 {
|
||||
for iNdEx := len(m.Folders) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
@ -2642,6 +2654,9 @@ func (m *ClusterConfig) ProtoSize() (n int) {
|
||||
n += 1 + l + sovBep(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.Secondary {
|
||||
n += 2
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@ -3430,6 +3445,26 @@ func (m *ClusterConfig) Unmarshal(dAtA []byte) error {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Secondary", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowBep
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Secondary = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipBep(dAtA[iNdEx:])
|
||||
|
@ -13,8 +13,8 @@ type TestModel struct {
|
||||
hash []byte
|
||||
weakHash uint32
|
||||
fromTemporary bool
|
||||
indexFn func(DeviceID, string, []FileInfo)
|
||||
ccFn func(DeviceID, ClusterConfig)
|
||||
indexFn func(string, []FileInfo)
|
||||
ccFn func(ClusterConfig)
|
||||
closedCh chan struct{}
|
||||
closedErr error
|
||||
}
|
||||
@ -25,18 +25,18 @@ func newTestModel() *TestModel {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TestModel) Index(deviceID DeviceID, folder string, files []FileInfo) error {
|
||||
func (t *TestModel) Index(_ Connection, folder string, files []FileInfo) error {
|
||||
if t.indexFn != nil {
|
||||
t.indexFn(deviceID, folder, files)
|
||||
t.indexFn(folder, files)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*TestModel) IndexUpdate(_ DeviceID, _ string, _ []FileInfo) error {
|
||||
func (*TestModel) IndexUpdate(Connection, string, []FileInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TestModel) Request(_ DeviceID, folder, name string, _, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error) {
|
||||
func (t *TestModel) Request(_ Connection, folder, name string, _, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error) {
|
||||
t.folder = folder
|
||||
t.name = name
|
||||
t.offset = offset
|
||||
@ -49,19 +49,19 @@ func (t *TestModel) Request(_ DeviceID, folder, name string, _, size int32, offs
|
||||
return &fakeRequestResponse{buf}, nil
|
||||
}
|
||||
|
||||
func (t *TestModel) Closed(_ string, err error) {
|
||||
func (t *TestModel) Closed(_ Connection, err error) {
|
||||
t.closedErr = err
|
||||
close(t.closedCh)
|
||||
}
|
||||
|
||||
func (t *TestModel) ClusterConfig(deviceID DeviceID, config ClusterConfig) error {
|
||||
func (t *TestModel) ClusterConfig(_ Connection, config ClusterConfig) error {
|
||||
if t.ccFn != nil {
|
||||
t.ccFn(deviceID, config)
|
||||
t.ccFn(config)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*TestModel) DownloadProgress(DeviceID, string, []FileDownloadProgressUpdate) error {
|
||||
func (*TestModel) DownloadProgress(Connection, string, []FileDownloadProgressUpdate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -43,12 +43,12 @@ const (
|
||||
// receives encrypted metadata and requests from the untrusted device, so it
|
||||
// must decrypt those and answer requests by encrypting the data.
|
||||
type encryptedModel struct {
|
||||
model Model
|
||||
model contextLessModel
|
||||
folderKeys *folderKeyRegistry
|
||||
keyGen *KeyGenerator
|
||||
}
|
||||
|
||||
func newEncryptedModel(model Model, folderKeys *folderKeyRegistry, keyGen *KeyGenerator) encryptedModel {
|
||||
func newEncryptedModel(model contextLessModel, folderKeys *folderKeyRegistry, keyGen *KeyGenerator) encryptedModel {
|
||||
return encryptedModel{
|
||||
model: model,
|
||||
folderKeys: folderKeys,
|
||||
@ -56,30 +56,30 @@ func newEncryptedModel(model Model, folderKeys *folderKeyRegistry, keyGen *KeyGe
|
||||
}
|
||||
}
|
||||
|
||||
func (e encryptedModel) Index(deviceID DeviceID, folder string, files []FileInfo) error {
|
||||
func (e encryptedModel) Index(folder string, files []FileInfo) error {
|
||||
if folderKey, ok := e.folderKeys.get(folder); ok {
|
||||
// incoming index data to be decrypted
|
||||
if err := decryptFileInfos(e.keyGen, files, folderKey); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return e.model.Index(deviceID, folder, files)
|
||||
return e.model.Index(folder, files)
|
||||
}
|
||||
|
||||
func (e encryptedModel) IndexUpdate(deviceID DeviceID, folder string, files []FileInfo) error {
|
||||
func (e encryptedModel) IndexUpdate(folder string, files []FileInfo) error {
|
||||
if folderKey, ok := e.folderKeys.get(folder); ok {
|
||||
// incoming index data to be decrypted
|
||||
if err := decryptFileInfos(e.keyGen, files, folderKey); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return e.model.IndexUpdate(deviceID, folder, files)
|
||||
return e.model.IndexUpdate(folder, files)
|
||||
}
|
||||
|
||||
func (e encryptedModel) Request(deviceID DeviceID, folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error) {
|
||||
func (e encryptedModel) Request(folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error) {
|
||||
folderKey, ok := e.folderKeys.get(folder)
|
||||
if !ok {
|
||||
return e.model.Request(deviceID, folder, name, blockNo, size, offset, hash, weakHash, fromTemporary)
|
||||
return e.model.Request(folder, name, blockNo, size, offset, hash, weakHash, fromTemporary)
|
||||
}
|
||||
|
||||
// Figure out the real file name, offset and size from the encrypted /
|
||||
@ -120,7 +120,7 @@ func (e encryptedModel) Request(deviceID DeviceID, folder, name string, blockNo,
|
||||
|
||||
// Perform that request and grab the data.
|
||||
|
||||
resp, err := e.model.Request(deviceID, folder, realName, blockNo, realSize, realOffset, realHash, 0, false)
|
||||
resp, err := e.model.Request(folder, realName, blockNo, realSize, realOffset, realHash, 0, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -142,21 +142,21 @@ func (e encryptedModel) Request(deviceID DeviceID, folder, name string, blockNo,
|
||||
return rawResponse{enc}, nil
|
||||
}
|
||||
|
||||
func (e encryptedModel) DownloadProgress(deviceID DeviceID, folder string, updates []FileDownloadProgressUpdate) error {
|
||||
func (e encryptedModel) DownloadProgress(folder string, updates []FileDownloadProgressUpdate) error {
|
||||
if _, ok := e.folderKeys.get(folder); !ok {
|
||||
return e.model.DownloadProgress(deviceID, folder, updates)
|
||||
return e.model.DownloadProgress(folder, updates)
|
||||
}
|
||||
|
||||
// Encrypted devices shouldn't send these - ignore them.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e encryptedModel) ClusterConfig(deviceID DeviceID, config ClusterConfig) error {
|
||||
return e.model.ClusterConfig(deviceID, config)
|
||||
func (e encryptedModel) ClusterConfig(config ClusterConfig) error {
|
||||
return e.model.ClusterConfig(config)
|
||||
}
|
||||
|
||||
func (e encryptedModel) Closed(connID string, err error) {
|
||||
e.model.Closed(connID, err)
|
||||
func (e encryptedModel) Closed(err error) {
|
||||
e.model.Closed(err)
|
||||
}
|
||||
|
||||
// The encryptedConnection sits between the model and the encrypted device. It
|
||||
|
@ -9,27 +9,27 @@ package protocol
|
||||
|
||||
import "golang.org/x/text/unicode/norm"
|
||||
|
||||
func makeNative(m Model) Model { return nativeModel{m} }
|
||||
func makeNative(m contextLessModel) contextLessModel { return nativeModel{m} }
|
||||
|
||||
type nativeModel struct {
|
||||
Model
|
||||
contextLessModel
|
||||
}
|
||||
|
||||
func (m nativeModel) Index(deviceID DeviceID, folder string, files []FileInfo) error {
|
||||
func (m nativeModel) Index(folder string, files []FileInfo) error {
|
||||
for i := range files {
|
||||
files[i].Name = norm.NFD.String(files[i].Name)
|
||||
}
|
||||
return m.Model.Index(deviceID, folder, files)
|
||||
return m.contextLessModel.Index(folder, files)
|
||||
}
|
||||
|
||||
func (m nativeModel) IndexUpdate(deviceID DeviceID, folder string, files []FileInfo) error {
|
||||
func (m nativeModel) IndexUpdate(folder string, files []FileInfo) error {
|
||||
for i := range files {
|
||||
files[i].Name = norm.NFD.String(files[i].Name)
|
||||
}
|
||||
return m.Model.IndexUpdate(deviceID, folder, files)
|
||||
return m.contextLessModel.IndexUpdate(folder, files)
|
||||
}
|
||||
|
||||
func (m nativeModel) Request(deviceID DeviceID, folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error) {
|
||||
func (m nativeModel) Request(folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error) {
|
||||
name = norm.NFD.String(name)
|
||||
return m.Model.Request(deviceID, folder, name, blockNo, size, offset, hash, weakHash, fromTemporary)
|
||||
return m.contextLessModel.Request(folder, name, blockNo, size, offset, hash, weakHash, fromTemporary)
|
||||
}
|
||||
|
@ -121,19 +121,34 @@ var (
|
||||
errFileHasNoBlocks = errors.New("file with empty block list")
|
||||
)
|
||||
|
||||
type contextLessModel interface {
|
||||
// An index was received from the peer device
|
||||
Index(folder string, files []FileInfo) error
|
||||
// An index update was received from the peer device
|
||||
IndexUpdate(folder string, files []FileInfo) error
|
||||
// A request was made by the peer device
|
||||
Request(folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error)
|
||||
// A cluster configuration message was received
|
||||
ClusterConfig(config ClusterConfig) error
|
||||
// The peer device closed the connection or an error occurred
|
||||
Closed(err error)
|
||||
// The peer device sent progress updates for the files it is currently downloading
|
||||
DownloadProgress(folder string, updates []FileDownloadProgressUpdate) error
|
||||
}
|
||||
|
||||
type Model interface {
|
||||
// An index was received from the peer device
|
||||
Index(deviceID DeviceID, folder string, files []FileInfo) error
|
||||
Index(conn Connection, folder string, files []FileInfo) error
|
||||
// An index update was received from the peer device
|
||||
IndexUpdate(deviceID DeviceID, folder string, files []FileInfo) error
|
||||
IndexUpdate(conn Connection, folder string, files []FileInfo) error
|
||||
// A request was made by the peer device
|
||||
Request(deviceID DeviceID, folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error)
|
||||
Request(conn Connection, folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error)
|
||||
// A cluster configuration message was received
|
||||
ClusterConfig(deviceID DeviceID, config ClusterConfig) error
|
||||
ClusterConfig(conn Connection, config ClusterConfig) error
|
||||
// The peer device closed the connection or an error occurred
|
||||
Closed(connID string, err error)
|
||||
Closed(conn Connection, err error)
|
||||
// The peer device sent progress updates for the files it is currently downloading
|
||||
DownloadProgress(deviceID DeviceID, folder string, updates []FileDownloadProgressUpdate) error
|
||||
DownloadProgress(conn Connection, folder string, updates []FileDownloadProgressUpdate) error
|
||||
}
|
||||
|
||||
type RequestResponse interface {
|
||||
@ -173,7 +188,7 @@ type rawConnection struct {
|
||||
ConnectionInfo
|
||||
|
||||
id DeviceID
|
||||
receiver Model
|
||||
model contextLessModel
|
||||
startTime time.Time
|
||||
|
||||
cr *countingReader
|
||||
@ -230,10 +245,16 @@ const (
|
||||
// Should not be modified in production code, just for testing.
|
||||
var CloseTimeout = 10 * time.Second
|
||||
|
||||
func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, closer io.Closer, receiver Model, connInfo ConnectionInfo, compress Compression, passwords map[string]string, keyGen *KeyGenerator) Connection {
|
||||
func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, closer io.Closer, model Model, connInfo ConnectionInfo, compress Compression, passwords map[string]string, keyGen *KeyGenerator) Connection {
|
||||
// We create the wrapper for the model first, as it needs to be passed
|
||||
// in at the lowest level in the stack. At the end of construction,
|
||||
// before returning, we add the connection to cwm so that it can be used
|
||||
// by the model.
|
||||
cwm := &connectionWrappingModel{model: model}
|
||||
|
||||
// Encryption / decryption is first (outermost) before conversion to
|
||||
// native path formats.
|
||||
nm := makeNative(receiver)
|
||||
nm := makeNative(cwm)
|
||||
em := newEncryptedModel(nm, newFolderKeyRegistry(keyGen, passwords), keyGen)
|
||||
|
||||
// We do the wire format conversion first (outermost) so that the
|
||||
@ -242,17 +263,18 @@ func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, closer
|
||||
ec := newEncryptedConnection(rc, rc, em.folderKeys, keyGen)
|
||||
wc := wireFormatConnection{ec}
|
||||
|
||||
cwm.conn = wc
|
||||
return wc
|
||||
}
|
||||
|
||||
func newRawConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, closer io.Closer, receiver Model, connInfo ConnectionInfo, compress Compression) *rawConnection {
|
||||
func newRawConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, closer io.Closer, receiver contextLessModel, connInfo ConnectionInfo, compress Compression) *rawConnection {
|
||||
cr := &countingReader{Reader: reader}
|
||||
cw := &countingWriter{Writer: writer}
|
||||
|
||||
return &rawConnection{
|
||||
ConnectionInfo: connInfo,
|
||||
id: deviceID,
|
||||
receiver: receiver,
|
||||
model: receiver,
|
||||
cr: cr,
|
||||
cw: cw,
|
||||
closer: closer,
|
||||
@ -463,7 +485,7 @@ func (c *rawConnection) dispatcherLoop() (err error) {
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case *ClusterConfig:
|
||||
err = c.receiver.ClusterConfig(c.id, *msg)
|
||||
err = c.model.ClusterConfig(*msg)
|
||||
|
||||
case *Index:
|
||||
err = c.handleIndex(*msg)
|
||||
@ -478,7 +500,7 @@ func (c *rawConnection) dispatcherLoop() (err error) {
|
||||
c.handleResponse(*msg)
|
||||
|
||||
case *DownloadProgress:
|
||||
err = c.receiver.DownloadProgress(c.id, msg.Folder, msg.Updates)
|
||||
err = c.model.DownloadProgress(msg.Folder, msg.Updates)
|
||||
}
|
||||
if err != nil {
|
||||
return newHandleError(err, msgContext)
|
||||
@ -581,12 +603,12 @@ func (c *rawConnection) readHeader(fourByteBuf []byte) (Header, error) {
|
||||
|
||||
func (c *rawConnection) handleIndex(im Index) error {
|
||||
l.Debugf("Index(%v, %v, %d file)", c.id, im.Folder, len(im.Files))
|
||||
return c.receiver.Index(c.id, im.Folder, im.Files)
|
||||
return c.model.Index(im.Folder, im.Files)
|
||||
}
|
||||
|
||||
func (c *rawConnection) handleIndexUpdate(im IndexUpdate) error {
|
||||
l.Debugf("queueing IndexUpdate(%v, %v, %d files)", c.id, im.Folder, len(im.Files))
|
||||
return c.receiver.IndexUpdate(c.id, im.Folder, im.Files)
|
||||
return c.model.IndexUpdate(im.Folder, im.Files)
|
||||
}
|
||||
|
||||
// checkIndexConsistency verifies a number of invariants on FileInfos received in
|
||||
@ -652,7 +674,7 @@ func checkFilename(name string) error {
|
||||
}
|
||||
|
||||
func (c *rawConnection) handleRequest(req Request) {
|
||||
res, err := c.receiver.Request(c.id, req.Folder, req.Name, int32(req.BlockNo), int32(req.Size), req.Offset, req.Hash, req.WeakHash, req.FromTemporary)
|
||||
res, err := c.model.Request(req.Folder, req.Name, int32(req.BlockNo), int32(req.Size), req.Offset, req.Hash, req.WeakHash, req.FromTemporary)
|
||||
if err != nil {
|
||||
c.send(context.Background(), &Response{
|
||||
ID: req.ID,
|
||||
@ -941,7 +963,7 @@ func (c *rawConnection) internalClose(err error) {
|
||||
|
||||
<-c.dispatcherLoopStopped
|
||||
|
||||
c.receiver.Closed(c.ConnectionID(), err)
|
||||
c.model.Closed(err)
|
||||
})
|
||||
}
|
||||
|
||||
@ -1069,3 +1091,35 @@ func messageContext(msg message) (string, error) {
|
||||
return "", errors.New("unknown or empty message")
|
||||
}
|
||||
}
|
||||
|
||||
// connectionWrappingModel takes the Model interface from the model package,
|
||||
// which expects the Connection as the first parameter in all methods, and
|
||||
// wraps it to conform to the protocol.Model interface.
|
||||
type connectionWrappingModel struct {
|
||||
conn Connection
|
||||
model Model
|
||||
}
|
||||
|
||||
func (c *connectionWrappingModel) Index(folder string, files []FileInfo) error {
|
||||
return c.model.Index(c.conn, folder, files)
|
||||
}
|
||||
|
||||
func (c *connectionWrappingModel) IndexUpdate(folder string, files []FileInfo) error {
|
||||
return c.model.IndexUpdate(c.conn, folder, files)
|
||||
}
|
||||
|
||||
func (c *connectionWrappingModel) Request(folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (RequestResponse, error) {
|
||||
return c.model.Request(c.conn, folder, name, blockNo, size, offset, hash, weakHash, fromTemporary)
|
||||
}
|
||||
|
||||
func (c *connectionWrappingModel) ClusterConfig(config ClusterConfig) error {
|
||||
return c.model.ClusterConfig(c.conn, config)
|
||||
}
|
||||
|
||||
func (c *connectionWrappingModel) Closed(err error) {
|
||||
c.model.Closed(c.conn, err)
|
||||
}
|
||||
|
||||
func (c *connectionWrappingModel) DownloadProgress(folder string, updates []FileDownloadProgressUpdate) error {
|
||||
return c.model.DownloadProgress(c.conn, folder, updates)
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ func TestCloseRace(t *testing.T) {
|
||||
indexReceived := make(chan struct{})
|
||||
unblockIndex := make(chan struct{})
|
||||
m0 := newTestModel()
|
||||
m0.indexFn = func(_ DeviceID, _ string, _ []FileInfo) {
|
||||
m0.indexFn = func(string, []FileInfo) {
|
||||
close(indexReceived)
|
||||
<-unblockIndex
|
||||
}
|
||||
@ -924,7 +924,7 @@ func TestDispatcherToCloseDeadlock(t *testing.T) {
|
||||
m := newTestModel()
|
||||
rw := testutils.NewBlockingRW()
|
||||
c := getRawConnection(NewConnection(c0ID, rw, &testutils.NoopRW{}, testutils.NoopCloser{}, m, new(mockedConnectionInfo), CompressionAlways, nil, testKeyGen))
|
||||
m.ccFn = func(devID DeviceID, cc ClusterConfig) {
|
||||
m.ccFn = func(ClusterConfig) {
|
||||
c.Close(errManual)
|
||||
}
|
||||
c.Start()
|
||||
|
@ -26,4 +26,5 @@ message DeviceConfiguration {
|
||||
int32 max_request_kib = 16 [(ext.goname) = "MaxRequestKiB", (ext.xml) = "maxRequestKiB", (ext.json) = "maxRequestKiB"];
|
||||
bool untrusted = 17;
|
||||
int32 remote_gui_port = 18 [(ext.goname) = "RemoteGUIPort", (ext.xml) = "remoteGUIPort", (ext.json) = "remoteGUIPort"];
|
||||
int32 multiple_connections = 19; // if >1 and supported by the other side, attempt to establish this many connections to the device
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ enum MessageCompression {
|
||||
|
||||
message ClusterConfig {
|
||||
repeated Folder folders = 1;
|
||||
bool secondary = 2;
|
||||
}
|
||||
|
||||
message Folder {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<configuration version="37">
|
||||
<folder id="default" label="" path="s1/" type="sendreceive" rescanIntervalS="10" fsWatcherEnabled="false" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
|
||||
<folder id="default" label="" path="s1/" type="sendreceive" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" introducedBy="">
|
||||
<encryptionPassword></encryptionPassword>
|
||||
@ -49,60 +49,6 @@
|
||||
<maxTotalSize>0</maxTotalSize>
|
||||
</xattrFilter>
|
||||
</folder>
|
||||
<folder id="¯\_(ツ)_/¯ Räksmörgås 动作 Адрес" label="" path="s12-1/" type="sendreceive" rescanIntervalS="10" fsWatcherEnabled="false" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" introducedBy="">
|
||||
<encryptionPassword></encryptionPassword>
|
||||
</device>
|
||||
<device id="MRIW7OK-NETT3M4-N6SBWME-N25O76W-YJKVXPH-FUMQJ3S-P57B74J-GBITBAC" introducedBy="">
|
||||
<encryptionPassword></encryptionPassword>
|
||||
</device>
|
||||
<minDiskFree unit="%">1</minDiskFree>
|
||||
<versioning>
|
||||
<cleanupIntervalS>3600</cleanupIntervalS>
|
||||
<fsPath></fsPath>
|
||||
<fsType>basic</fsType>
|
||||
</versioning>
|
||||
<copiers>1</copiers>
|
||||
<pullerMaxPendingKiB>0</pullerMaxPendingKiB>
|
||||
<hashers>0</hashers>
|
||||
<order>random</order>
|
||||
<ignoreDelete>false</ignoreDelete>
|
||||
<scanProgressIntervalS>0</scanProgressIntervalS>
|
||||
<pullerPauseS>0</pullerPauseS>
|
||||
<maxConflicts>-1</maxConflicts>
|
||||
<disableSparseFiles>false</disableSparseFiles>
|
||||
<disableTempIndexes>false</disableTempIndexes>
|
||||
<paused>false</paused>
|
||||
<weakHashThresholdPct>25</weakHashThresholdPct>
|
||||
<markerName>.stfolder</markerName>
|
||||
<copyOwnershipFromParent>false</copyOwnershipFromParent>
|
||||
<modTimeWindowS>0</modTimeWindowS>
|
||||
<maxConcurrentWrites>2</maxConcurrentWrites>
|
||||
<disableFsync>false</disableFsync>
|
||||
<blockPullOrder>standard</blockPullOrder>
|
||||
<copyRangeMethod>standard</copyRangeMethod>
|
||||
<caseSensitiveFS>false</caseSensitiveFS>
|
||||
<junctionsAsDirs>true</junctionsAsDirs>
|
||||
<syncOwnership>false</syncOwnership>
|
||||
<sendOwnership>false</sendOwnership>
|
||||
<syncXattrs>false</syncXattrs>
|
||||
<sendXattrs>false</sendXattrs>
|
||||
<xattrFilter>
|
||||
<maxSingleEntrySize>0</maxSingleEntrySize>
|
||||
<maxTotalSize>0</maxTotalSize>
|
||||
</xattrFilter>
|
||||
</folder>
|
||||
<device id="EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK" name="s4" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
|
||||
<address>tcp://127.0.0.1:22004</address>
|
||||
<paused>false</paused>
|
||||
<autoAcceptFolders>false</autoAcceptFolders>
|
||||
<maxSendKbps>0</maxSendKbps>
|
||||
<maxRecvKbps>0</maxRecvKbps>
|
||||
<maxRequestKiB>0</maxRequestKiB>
|
||||
<untrusted>false</untrusted>
|
||||
<remoteGUIPort>0</remoteGUIPort>
|
||||
</device>
|
||||
<device id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" name="s1" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
|
||||
<address>tcp://127.0.0.1:22001</address>
|
||||
<paused>false</paused>
|
||||
@ -122,26 +68,7 @@
|
||||
<maxRequestKiB>0</maxRequestKiB>
|
||||
<untrusted>false</untrusted>
|
||||
<remoteGUIPort>0</remoteGUIPort>
|
||||
</device>
|
||||
<device id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU" name="s3" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
|
||||
<address>tcp://127.0.0.1:22003</address>
|
||||
<paused>false</paused>
|
||||
<autoAcceptFolders>false</autoAcceptFolders>
|
||||
<maxSendKbps>0</maxSendKbps>
|
||||
<maxRecvKbps>0</maxRecvKbps>
|
||||
<maxRequestKiB>0</maxRequestKiB>
|
||||
<untrusted>false</untrusted>
|
||||
<remoteGUIPort>0</remoteGUIPort>
|
||||
</device>
|
||||
<device id="7PBCTLL-JJRYBSA-MOWZRKL-MSDMN4N-4US4OMX-SYEXUS4-HSBGNRY-CZXRXAT" name="s4" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
|
||||
<address>tcp://127.0.0.1:22004</address>
|
||||
<paused>false</paused>
|
||||
<autoAcceptFolders>false</autoAcceptFolders>
|
||||
<maxSendKbps>0</maxSendKbps>
|
||||
<maxRecvKbps>0</maxRecvKbps>
|
||||
<maxRequestKiB>0</maxRequestKiB>
|
||||
<untrusted>false</untrusted>
|
||||
<remoteGUIPort>0</remoteGUIPort>
|
||||
<multipleConnections>4</multipleConnections>
|
||||
</device>
|
||||
<gui enabled="true" tls="false" debugging="true">
|
||||
<address>127.0.0.1:8081</address>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<configuration version="37">
|
||||
<folder id="default" label="" path="s2" type="sendreceive" rescanIntervalS="15" fsWatcherEnabled="false" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
|
||||
<folder id="default" label="" path="s2" type="sendreceive" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" introducedBy="">
|
||||
<encryptionPassword></encryptionPassword>
|
||||
@ -46,94 +46,6 @@
|
||||
<maxTotalSize>0</maxTotalSize>
|
||||
</xattrFilter>
|
||||
</folder>
|
||||
<folder id="s23" label="" path="s23-2" type="sendreceive" rescanIntervalS="15" fsWatcherEnabled="false" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="MRIW7OK-NETT3M4-N6SBWME-N25O76W-YJKVXPH-FUMQJ3S-P57B74J-GBITBAC" introducedBy="">
|
||||
<encryptionPassword></encryptionPassword>
|
||||
</device>
|
||||
<device id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU" introducedBy="">
|
||||
<encryptionPassword></encryptionPassword>
|
||||
</device>
|
||||
<minDiskFree unit="%">1</minDiskFree>
|
||||
<versioning>
|
||||
<cleanupIntervalS>3600</cleanupIntervalS>
|
||||
<fsPath></fsPath>
|
||||
<fsType>basic</fsType>
|
||||
</versioning>
|
||||
<copiers>1</copiers>
|
||||
<pullerMaxPendingKiB>0</pullerMaxPendingKiB>
|
||||
<hashers>0</hashers>
|
||||
<order>random</order>
|
||||
<ignoreDelete>false</ignoreDelete>
|
||||
<scanProgressIntervalS>0</scanProgressIntervalS>
|
||||
<pullerPauseS>0</pullerPauseS>
|
||||
<maxConflicts>-1</maxConflicts>
|
||||
<disableSparseFiles>false</disableSparseFiles>
|
||||
<disableTempIndexes>false</disableTempIndexes>
|
||||
<paused>false</paused>
|
||||
<weakHashThresholdPct>25</weakHashThresholdPct>
|
||||
<markerName>.stfolder</markerName>
|
||||
<copyOwnershipFromParent>false</copyOwnershipFromParent>
|
||||
<modTimeWindowS>0</modTimeWindowS>
|
||||
<maxConcurrentWrites>2</maxConcurrentWrites>
|
||||
<disableFsync>false</disableFsync>
|
||||
<blockPullOrder>standard</blockPullOrder>
|
||||
<copyRangeMethod>standard</copyRangeMethod>
|
||||
<caseSensitiveFS>false</caseSensitiveFS>
|
||||
<junctionsAsDirs>true</junctionsAsDirs>
|
||||
<syncOwnership>false</syncOwnership>
|
||||
<sendOwnership>false</sendOwnership>
|
||||
<syncXattrs>false</syncXattrs>
|
||||
<sendXattrs>false</sendXattrs>
|
||||
<xattrFilter>
|
||||
<maxSingleEntrySize>0</maxSingleEntrySize>
|
||||
<maxTotalSize>0</maxTotalSize>
|
||||
</xattrFilter>
|
||||
</folder>
|
||||
<folder id="¯\_(ツ)_/¯ Räksmörgås 动作 Адрес" label="" path="s12-2" type="sendreceive" rescanIntervalS="15" fsWatcherEnabled="false" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" introducedBy="">
|
||||
<encryptionPassword></encryptionPassword>
|
||||
</device>
|
||||
<device id="MRIW7OK-NETT3M4-N6SBWME-N25O76W-YJKVXPH-FUMQJ3S-P57B74J-GBITBAC" introducedBy="">
|
||||
<encryptionPassword></encryptionPassword>
|
||||
</device>
|
||||
<minDiskFree unit="%">1</minDiskFree>
|
||||
<versioning>
|
||||
<cleanupIntervalS>3600</cleanupIntervalS>
|
||||
<fsPath></fsPath>
|
||||
<fsType>basic</fsType>
|
||||
</versioning>
|
||||
<copiers>1</copiers>
|
||||
<pullerMaxPendingKiB>0</pullerMaxPendingKiB>
|
||||
<hashers>0</hashers>
|
||||
<order>random</order>
|
||||
<ignoreDelete>false</ignoreDelete>
|
||||
<scanProgressIntervalS>0</scanProgressIntervalS>
|
||||
<pullerPauseS>0</pullerPauseS>
|
||||
<maxConflicts>-1</maxConflicts>
|
||||
<disableSparseFiles>false</disableSparseFiles>
|
||||
<disableTempIndexes>false</disableTempIndexes>
|
||||
<paused>false</paused>
|
||||
<weakHashThresholdPct>25</weakHashThresholdPct>
|
||||
<markerName>.stfolder</markerName>
|
||||
<copyOwnershipFromParent>false</copyOwnershipFromParent>
|
||||
<modTimeWindowS>0</modTimeWindowS>
|
||||
<maxConcurrentWrites>2</maxConcurrentWrites>
|
||||
<disableFsync>false</disableFsync>
|
||||
<blockPullOrder>standard</blockPullOrder>
|
||||
<copyRangeMethod>standard</copyRangeMethod>
|
||||
<caseSensitiveFS>false</caseSensitiveFS>
|
||||
<junctionsAsDirs>true</junctionsAsDirs>
|
||||
<syncOwnership>false</syncOwnership>
|
||||
<sendOwnership>false</sendOwnership>
|
||||
<syncXattrs>false</syncXattrs>
|
||||
<sendXattrs>false</sendXattrs>
|
||||
<xattrFilter>
|
||||
<maxSingleEntrySize>0</maxSingleEntrySize>
|
||||
<maxTotalSize>0</maxTotalSize>
|
||||
</xattrFilter>
|
||||
</folder>
|
||||
<device id="I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU" name="s1" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
|
||||
<address>tcp://127.0.0.1:22001</address>
|
||||
<paused>false</paused>
|
||||
@ -143,6 +55,7 @@
|
||||
<maxRequestKiB>0</maxRequestKiB>
|
||||
<untrusted>false</untrusted>
|
||||
<remoteGUIPort>0</remoteGUIPort>
|
||||
<multipleConnections>4</multipleConnections>
|
||||
</device>
|
||||
<device id="MRIW7OK-NETT3M4-N6SBWME-N25O76W-YJKVXPH-FUMQJ3S-P57B74J-GBITBAC" name="s2" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
|
||||
<address>tcp://127.0.0.1:22002</address>
|
||||
@ -154,16 +67,6 @@
|
||||
<untrusted>false</untrusted>
|
||||
<remoteGUIPort>0</remoteGUIPort>
|
||||
</device>
|
||||
<device id="373HSRP-QLPNLIE-JYKZVQF-P4PKZ63-R2ZE6K3-YD442U2-JHBGBQG-WWXAHAU" name="s3" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
|
||||
<address>tcp://127.0.0.1:22003</address>
|
||||
<paused>false</paused>
|
||||
<autoAcceptFolders>false</autoAcceptFolders>
|
||||
<maxSendKbps>0</maxSendKbps>
|
||||
<maxRecvKbps>0</maxRecvKbps>
|
||||
<maxRequestKiB>0</maxRequestKiB>
|
||||
<untrusted>false</untrusted>
|
||||
<remoteGUIPort>0</remoteGUIPort>
|
||||
</device>
|
||||
<gui enabled="true" tls="false" debugging="true">
|
||||
<address>127.0.0.1:8082</address>
|
||||
<apikey>abc123</apikey>
|
||||
|
Loading…
Reference in New Issue
Block a user