1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-08 05:47:07 +09:00

GO-3171: add p2p status service

Signed-off-by: AnastasiaShemyakinskaya <shem98a@mail.ru>
This commit is contained in:
AnastasiaShemyakinskaya 2024-05-17 20:19:55 +02:00
parent f8b925eec4
commit cd93d89a84
No known key found for this signature in database
GPG key ID: CCD60ED83B103281
23 changed files with 2058 additions and 407 deletions

View file

@ -165,3 +165,9 @@ packages:
github.com/anyproto/anytype-heart/core/block/object/idresolver:
interfaces:
Resolver:
github.com/anyproto/anytype-heart/space/spacecore/clientserver:
interfaces:
ClientServer:
github.com/anyproto/anytype-heart/core/syncstatus/p2p:
interfaces:
StatusUpdateSender:

View file

@ -73,6 +73,7 @@ import (
"github.com/anyproto/anytype-heart/core/recordsbatcher"
"github.com/anyproto/anytype-heart/core/subscription"
"github.com/anyproto/anytype-heart/core/syncstatus"
"github.com/anyproto/anytype-heart/core/syncstatus/p2p"
"github.com/anyproto/anytype-heart/core/wallet"
"github.com/anyproto/anytype-heart/metrics"
"github.com/anyproto/anytype-heart/pkg/lib/core"
@ -228,6 +229,7 @@ func Bootstrap(a *app.App, components ...app.Component) {
Register(virtualspaceservice.New()).
Register(spacecore.New()).
Register(idresolver.New()).
Register(p2p.NewObservers()).
Register(localdiscovery.New()).
Register(peermanager.New()).
Register(typeprovider.New()).

View file

@ -0,0 +1,288 @@
// Code generated by mockery. DO NOT EDIT.
package mock_p2p
import (
context "context"
app "github.com/anyproto/any-sync/app"
mock "github.com/stretchr/testify/mock"
peerstatus "github.com/anyproto/any-sync/commonspace/peerstatus"
)
// MockStatusUpdateSender is an autogenerated mock type for the StatusUpdateSender type
type MockStatusUpdateSender struct {
mock.Mock
}
type MockStatusUpdateSender_Expecter struct {
mock *mock.Mock
}
func (_m *MockStatusUpdateSender) EXPECT() *MockStatusUpdateSender_Expecter {
return &MockStatusUpdateSender_Expecter{mock: &_m.Mock}
}
// Close provides a mock function with given fields: ctx
func (_m *MockStatusUpdateSender) Close(ctx context.Context) error {
ret := _m.Called(ctx)
if len(ret) == 0 {
panic("no return value specified for Close")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
r0 = rf(ctx)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockStatusUpdateSender_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
type MockStatusUpdateSender_Close_Call struct {
*mock.Call
}
// Close is a helper method to define mock.On call
// - ctx context.Context
func (_e *MockStatusUpdateSender_Expecter) Close(ctx interface{}) *MockStatusUpdateSender_Close_Call {
return &MockStatusUpdateSender_Close_Call{Call: _e.mock.On("Close", ctx)}
}
func (_c *MockStatusUpdateSender_Close_Call) Run(run func(ctx context.Context)) *MockStatusUpdateSender_Close_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context))
})
return _c
}
func (_c *MockStatusUpdateSender_Close_Call) Return(err error) *MockStatusUpdateSender_Close_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockStatusUpdateSender_Close_Call) RunAndReturn(run func(context.Context) error) *MockStatusUpdateSender_Close_Call {
_c.Call.Return(run)
return _c
}
// Init provides a mock function with given fields: a
func (_m *MockStatusUpdateSender) Init(a *app.App) error {
ret := _m.Called(a)
if len(ret) == 0 {
panic("no return value specified for Init")
}
var r0 error
if rf, ok := ret.Get(0).(func(*app.App) error); ok {
r0 = rf(a)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockStatusUpdateSender_Init_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Init'
type MockStatusUpdateSender_Init_Call struct {
*mock.Call
}
// Init is a helper method to define mock.On call
// - a *app.App
func (_e *MockStatusUpdateSender_Expecter) Init(a interface{}) *MockStatusUpdateSender_Init_Call {
return &MockStatusUpdateSender_Init_Call{Call: _e.mock.On("Init", a)}
}
func (_c *MockStatusUpdateSender_Init_Call) Run(run func(a *app.App)) *MockStatusUpdateSender_Init_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*app.App))
})
return _c
}
func (_c *MockStatusUpdateSender_Init_Call) Return(err error) *MockStatusUpdateSender_Init_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockStatusUpdateSender_Init_Call) RunAndReturn(run func(*app.App) error) *MockStatusUpdateSender_Init_Call {
_c.Call.Return(run)
return _c
}
// Name provides a mock function with given fields:
func (_m *MockStatusUpdateSender) Name() string {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Name")
}
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// MockStatusUpdateSender_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name'
type MockStatusUpdateSender_Name_Call struct {
*mock.Call
}
// Name is a helper method to define mock.On call
func (_e *MockStatusUpdateSender_Expecter) Name() *MockStatusUpdateSender_Name_Call {
return &MockStatusUpdateSender_Name_Call{Call: _e.mock.On("Name")}
}
func (_c *MockStatusUpdateSender_Name_Call) Run(run func()) *MockStatusUpdateSender_Name_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockStatusUpdateSender_Name_Call) Return(name string) *MockStatusUpdateSender_Name_Call {
_c.Call.Return(name)
return _c
}
func (_c *MockStatusUpdateSender_Name_Call) RunAndReturn(run func() string) *MockStatusUpdateSender_Name_Call {
_c.Call.Return(run)
return _c
}
// Run provides a mock function with given fields: ctx
func (_m *MockStatusUpdateSender) Run(ctx context.Context) error {
ret := _m.Called(ctx)
if len(ret) == 0 {
panic("no return value specified for Run")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
r0 = rf(ctx)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockStatusUpdateSender_Run_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Run'
type MockStatusUpdateSender_Run_Call struct {
*mock.Call
}
// Run is a helper method to define mock.On call
// - ctx context.Context
func (_e *MockStatusUpdateSender_Expecter) Run(ctx interface{}) *MockStatusUpdateSender_Run_Call {
return &MockStatusUpdateSender_Run_Call{Call: _e.mock.On("Run", ctx)}
}
func (_c *MockStatusUpdateSender_Run_Call) Run(run func(ctx context.Context)) *MockStatusUpdateSender_Run_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context))
})
return _c
}
func (_c *MockStatusUpdateSender_Run_Call) Return(err error) *MockStatusUpdateSender_Run_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockStatusUpdateSender_Run_Call) RunAndReturn(run func(context.Context) error) *MockStatusUpdateSender_Run_Call {
_c.Call.Return(run)
return _c
}
// SendNewStatus provides a mock function with given fields: status
func (_m *MockStatusUpdateSender) SendNewStatus(status peerstatus.Status) {
_m.Called(status)
}
// MockStatusUpdateSender_SendNewStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendNewStatus'
type MockStatusUpdateSender_SendNewStatus_Call struct {
*mock.Call
}
// SendNewStatus is a helper method to define mock.On call
// - status peerstatus.Status
func (_e *MockStatusUpdateSender_Expecter) SendNewStatus(status interface{}) *MockStatusUpdateSender_SendNewStatus_Call {
return &MockStatusUpdateSender_SendNewStatus_Call{Call: _e.mock.On("SendNewStatus", status)}
}
func (_c *MockStatusUpdateSender_SendNewStatus_Call) Run(run func(status peerstatus.Status)) *MockStatusUpdateSender_SendNewStatus_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(peerstatus.Status))
})
return _c
}
func (_c *MockStatusUpdateSender_SendNewStatus_Call) Return() *MockStatusUpdateSender_SendNewStatus_Call {
_c.Call.Return()
return _c
}
func (_c *MockStatusUpdateSender_SendNewStatus_Call) RunAndReturn(run func(peerstatus.Status)) *MockStatusUpdateSender_SendNewStatus_Call {
_c.Call.Return(run)
return _c
}
// SendPeerUpdate provides a mock function with given fields:
func (_m *MockStatusUpdateSender) SendPeerUpdate() {
_m.Called()
}
// MockStatusUpdateSender_SendPeerUpdate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendPeerUpdate'
type MockStatusUpdateSender_SendPeerUpdate_Call struct {
*mock.Call
}
// SendPeerUpdate is a helper method to define mock.On call
func (_e *MockStatusUpdateSender_Expecter) SendPeerUpdate() *MockStatusUpdateSender_SendPeerUpdate_Call {
return &MockStatusUpdateSender_SendPeerUpdate_Call{Call: _e.mock.On("SendPeerUpdate")}
}
func (_c *MockStatusUpdateSender_SendPeerUpdate_Call) Run(run func()) *MockStatusUpdateSender_SendPeerUpdate_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockStatusUpdateSender_SendPeerUpdate_Call) Return() *MockStatusUpdateSender_SendPeerUpdate_Call {
_c.Call.Return()
return _c
}
func (_c *MockStatusUpdateSender_SendPeerUpdate_Call) RunAndReturn(run func()) *MockStatusUpdateSender_SendPeerUpdate_Call {
_c.Call.Return(run)
return _c
}
// NewMockStatusUpdateSender creates a new instance of MockStatusUpdateSender. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockStatusUpdateSender(t interface {
mock.TestingT
Cleanup(func())
}) *MockStatusUpdateSender {
mock := &MockStatusUpdateSender{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View file

@ -0,0 +1,170 @@
package p2p
import (
"context"
"testing"
"github.com/anyproto/any-sync/commonspace/peerstatus"
"github.com/stretchr/testify/assert"
"github.com/anyproto/anytype-heart/pb"
)
func TestObservers_BroadcastStatus(t *testing.T) {
t.Run("TestObservers_BroadcastStatus on registered observers", func(t *testing.T) {
// given
observers := NewObservers()
status := newFixture(t, "spaceId1", pb.EventP2PStatus_NotConnected)
err := status.Run(context.Background())
assert.Nil(t, err)
observers.AddObserver("spaceId1", status)
status2 := newFixture(t, "spaceId2", pb.EventP2PStatus_NotConnected)
err = status2.Run(context.Background())
assert.Nil(t, err)
observers.AddObserver("spaceId2", status2)
// when
status.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId1",
Status: pb.EventP2PStatus_Connected,
},
},
},
},
})
status2.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId2",
Status: pb.EventP2PStatus_Connected,
},
},
},
},
})
observers.BroadcastStatus(peerstatus.Connected)
for status.StatusUpdateSender.(*p2pStatus).status != peerstatus.Connected {
}
for status2.StatusUpdateSender.(*p2pStatus).status != peerstatus.Connected {
}
// then
assert.Equal(t, peerstatus.Connected, status.StatusUpdateSender.(*p2pStatus).status)
assert.Equal(t, peerstatus.Connected, status2.StatusUpdateSender.(*p2pStatus).status)
err = status.Close(context.Background())
assert.Nil(t, err)
err = status2.Close(context.Background())
assert.Nil(t, err)
})
}
func TestObservers_BroadcastPeerUpdate(t *testing.T) {
t.Run("BroadcastPeerUpdate on registered observers", func(t *testing.T) {
// given
observers := NewObservers()
status := newFixture(t, "spaceId1", pb.EventP2PStatus_NotConnected)
err := status.Run(context.Background())
assert.Nil(t, err)
observers.AddObserver("spaceId1", status)
status2 := newFixture(t, "spaceId2", pb.EventP2PStatus_NotConnected)
err = status2.Run(context.Background())
assert.Nil(t, err)
observers.AddObserver("spaceId2", status2)
// when
status.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId1",
Status: pb.EventP2PStatus_Connected,
},
},
},
},
})
status2.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId2",
Status: pb.EventP2PStatus_Connected,
},
},
},
},
})
status.store.UpdateLocalPeer("peerId", []string{"spaceId1"})
status2.store.UpdateLocalPeer("peerId", []string{"spaceId2"})
observers.BroadcastPeerUpdate()
for status.StatusUpdateSender.(*p2pStatus).status != peerstatus.Connected {
}
for status2.StatusUpdateSender.(*p2pStatus).status != peerstatus.Connected {
}
// then
assert.Equal(t, peerstatus.Connected, status.StatusUpdateSender.(*p2pStatus).status)
assert.Equal(t, peerstatus.Connected, status2.StatusUpdateSender.(*p2pStatus).status)
err = status.Close(context.Background())
assert.Nil(t, err)
err = status2.Close(context.Background())
assert.Nil(t, err)
})
}
func TestObservers_SendPeerUpdate(t *testing.T) {
t.Run("BroadcastPeerUpdate on registered observers", func(t *testing.T) {
// given
observers := NewObservers()
status := newFixture(t, "spaceId1", pb.EventP2PStatus_NotConnected)
err := status.Run(context.Background())
assert.Nil(t, err)
observers.AddObserver("spaceId1", status)
status2 := newFixture(t, "spaceId2", pb.EventP2PStatus_NotConnected)
err = status2.Run(context.Background())
assert.Nil(t, err)
observers.AddObserver("spaceId2", status2)
// when
status.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId1",
Status: pb.EventP2PStatus_Connected,
},
},
},
},
})
status.store.UpdateLocalPeer("peerId", []string{"spaceId1"})
observers.SendPeerUpdate([]string{"spaceId1"})
for status.StatusUpdateSender.(*p2pStatus).status != peerstatus.Connected {
}
// then
assert.Equal(t, peerstatus.Connected, status.StatusUpdateSender.(*p2pStatus).status)
assert.Equal(t, peerstatus.NotConnected, status2.StatusUpdateSender.(*p2pStatus).status)
err = status.Close(context.Background())
assert.Nil(t, err)
err = status2.Close(context.Background())
assert.Nil(t, err)
})
}

View file

@ -0,0 +1,62 @@
package p2p
import (
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/peerstatus"
"github.com/anyproto/anytype-heart/pkg/lib/logging"
)
var log = logging.Logger(observerServiceName)
const observerServiceName = "core.syncstatus.p2p.observers"
type ObserverComponent interface {
app.Component
AddObserver(spaceId string, observer StatusUpdateSender)
BroadcastStatus(status peerstatus.Status)
SendPeerUpdate(spaceIds []string)
BroadcastPeerUpdate()
}
type Observers struct {
observer map[string]StatusUpdateSender
}
func (o *Observers) SendPeerUpdate(spaceIds []string) {
for _, spaceId := range spaceIds {
if observer, ok := o.observer[spaceId]; ok {
observer.SendPeerUpdate()
return
}
log.Errorf("observer not registered for space %s", spaceIds)
}
}
func (o *Observers) BroadcastStatus(status peerstatus.Status) {
for _, observer := range o.observer {
observer.SendNewStatus(status)
}
}
func (o *Observers) BroadcastPeerUpdate() {
for _, observer := range o.observer {
observer.SendPeerUpdate()
}
}
func (o *Observers) Init(a *app.App) (err error) {
return
}
func (o *Observers) Name() (name string) {
return observerServiceName
}
func (o *Observers) AddObserver(spaceId string, observer StatusUpdateSender) {
o.observer[spaceId] = observer
}
func NewObservers() *Observers {
return &Observers{observer: make(map[string]StatusUpdateSender, 0)}
}

View file

@ -0,0 +1,147 @@
package p2p
import (
"context"
"sync"
"time"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/peerstatus"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/space/spacecore/peerstore"
)
const CName = "core.syncstatus.p2p"
type StatusUpdateSender interface {
app.ComponentRunnable
SendPeerUpdate()
SendNewStatus(status peerstatus.Status)
}
type p2pStatus struct {
spaceId string
peerStore peerstore.PeerStore
eventSender event.Sender
contextCancel context.CancelFunc
ctx context.Context
sync.Mutex
status peerstatus.Status
forceCheckSpace chan struct{}
updateStatus chan peerstatus.Status
}
func NewP2PStatus(spaceId string) StatusUpdateSender {
return &p2pStatus{forceCheckSpace: make(chan struct{}), updateStatus: make(chan peerstatus.Status), spaceId: spaceId}
}
func (p *p2pStatus) Init(a *app.App) (err error) {
p.peerStore = app.MustComponent[peerstore.PeerStore](a)
p.eventSender = app.MustComponent[event.Sender](a)
observerComponent := app.MustComponent[ObserverComponent](a)
observerComponent.AddObserver(p.spaceId, p)
return
}
func (p *p2pStatus) Name() (name string) {
return CName
}
func (p *p2pStatus) Run(ctx context.Context) (err error) {
p.ctx, p.contextCancel = context.WithCancel(context.Background())
go p.checkP2PDevices()
return nil
}
func (p *p2pStatus) Close(ctx context.Context) (err error) {
if p.contextCancel != nil {
p.contextCancel()
}
return
}
func (p *p2pStatus) SendPeerUpdate() {
p.forceCheckSpace <- struct{}{}
}
func (p *p2pStatus) SendNewStatus(status peerstatus.Status) {
p.updateStatus <- status
}
func (p *p2pStatus) checkP2PDevices() {
timer := time.NewTimer(10 * time.Second)
defer timer.Stop()
p.updateSpaceP2PStatus()
for {
select {
case <-p.ctx.Done():
return
case <-timer.C:
p.updateSpaceP2PStatus()
case <-p.forceCheckSpace:
p.updateSpaceP2PStatus()
case newStatus := <-p.updateStatus:
p.sendNewStatus(newStatus)
}
}
}
func (p *p2pStatus) updateSpaceP2PStatus() {
p.Lock()
defer p.Unlock()
peerIds := p.peerStore.LocalPeerIds(p.spaceId)
if p.status != peerstatus.Unknown {
// avoiding sending of redundant event
if p.status == peerstatus.Connected && len(peerIds) == 0 {
p.sendEvent(p.spaceId, pb.EventP2PStatus_NotConnected)
p.status = peerstatus.NotConnected
}
if (p.status == peerstatus.NotConnected || p.status == peerstatus.NotPossible) && len(peerIds) > 0 {
p.sendEvent(p.spaceId, pb.EventP2PStatus_Connected)
p.status = peerstatus.Connected
}
} else {
if len(peerIds) > 0 {
p.sendEvent(p.spaceId, pb.EventP2PStatus_Connected)
p.status = peerstatus.Connected
} else {
p.sendEvent(p.spaceId, pb.EventP2PStatus_NotConnected)
p.status = peerstatus.NotConnected
}
}
}
func (p *p2pStatus) sendNewStatus(status peerstatus.Status) {
var pbStatus pb.EventP2PStatusStatus
switch status {
case peerstatus.Connected:
pbStatus = pb.EventP2PStatus_Connected
case peerstatus.NotConnected:
pbStatus = pb.EventP2PStatus_NotConnected
case peerstatus.NotPossible:
pbStatus = pb.EventP2PStatus_NotPossible
}
p.Lock()
p.status = status
p.Unlock()
p.sendEvent(p.spaceId, pbStatus)
}
func (p *p2pStatus) sendEvent(spaceId string, status pb.EventP2PStatusStatus) {
p.eventSender.Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: spaceId,
Status: status,
},
},
},
},
})
}

View file

@ -0,0 +1,353 @@
package p2p
import (
"context"
"testing"
"time"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/peerstatus"
"github.com/anyproto/any-sync/nodeconf/mock_nodeconf"
"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"
"github.com/anyproto/anytype-heart/core/event/mock_event"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/space/spacecore/peerstore"
"github.com/anyproto/anytype-heart/tests/testutil"
)
type fixture struct {
StatusUpdateSender
sender *mock_event.MockSender
service *mock_nodeconf.MockService
store peerstore.PeerStore
}
func TestP2PStatus_Init(t *testing.T) {
t.Run("success", func(t *testing.T) {
// given
f := newFixture(t, "spaceId", pb.EventP2PStatus_NotConnected)
// when
err := f.Run(context.Background())
assert.Nil(t, err)
// then
err = f.Close(context.Background())
assert.Nil(t, err)
})
}
func TestP2pStatus_SendNewStatus(t *testing.T) {
t.Run("send NotPossible status", func(t *testing.T) {
// given
f := newFixture(t, "spaceId", pb.EventP2PStatus_NotConnected)
err := f.Run(context.Background())
assert.Nil(t, err)
// when
f.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId",
Status: pb.EventP2PStatus_NotPossible,
},
},
},
},
})
f.SendNewStatus(peerstatus.NotPossible)
// then
status := f.StatusUpdateSender.(*p2pStatus)
assert.NotNil(t, status)
assert.Equal(t, peerstatus.NotPossible, status.status)
err = f.Close(context.Background())
assert.Nil(t, err)
})
t.Run("send NotConnected status", func(t *testing.T) {
// given
f := newFixture(t, "spaceId", pb.EventP2PStatus_NotConnected)
err := f.Run(context.Background())
assert.Nil(t, err)
// when
f.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId",
Status: pb.EventP2PStatus_NotConnected,
},
},
},
},
})
f.SendNewStatus(peerstatus.NotConnected)
// then
status := f.StatusUpdateSender.(*p2pStatus)
assert.NotNil(t, status)
assert.Equal(t, peerstatus.NotConnected, status.status)
err = f.Close(context.Background())
assert.Nil(t, err)
})
t.Run("send NotConnected status", func(t *testing.T) {
// given
f := newFixture(t, "spaceId", pb.EventP2PStatus_NotConnected)
err := f.Run(context.Background())
assert.Nil(t, err)
// when
f.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId",
Status: pb.EventP2PStatus_NotConnected,
},
},
},
},
})
f.SendNewStatus(peerstatus.NotConnected)
// then
status := f.StatusUpdateSender.(*p2pStatus)
assert.NotNil(t, status)
assert.Equal(t, peerstatus.NotConnected, status.status)
err = f.Close(context.Background())
assert.Nil(t, err)
})
t.Run("send Connected status", func(t *testing.T) {
// given
f := newFixture(t, "spaceId", pb.EventP2PStatus_NotConnected)
err := f.Run(context.Background())
assert.Nil(t, err)
// when
f.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId",
Status: pb.EventP2PStatus_Connected,
},
},
},
},
})
f.SendNewStatus(peerstatus.Connected)
// then
status := f.StatusUpdateSender.(*p2pStatus)
assert.NotNil(t, status)
assert.Equal(t, peerstatus.Connected, status.status)
err = f.Close(context.Background())
assert.Nil(t, err)
})
}
func TestP2pStatus_SendPeerUpdate(t *testing.T) {
t.Run("send Connected status, because we have peers", func(t *testing.T) {
// given
f := newFixture(t, "spaceId", pb.EventP2PStatus_Connected)
f.store.UpdateLocalPeer("peerId", []string{"spaceId"})
// when
err := f.Run(context.Background())
assert.Nil(t, err)
f.SendPeerUpdate()
// then
err = f.Close(context.Background())
assert.Nil(t, err)
status := f.StatusUpdateSender.(*p2pStatus)
assert.NotNil(t, status)
assert.Equal(t, peerstatus.Connected, status.status)
})
t.Run("send NotConnected status, because we have peer were disconnected", func(t *testing.T) {
// given
f := newFixture(t, "spaceId", pb.EventP2PStatus_Connected)
f.store.UpdateLocalPeer("peerId", []string{"spaceId"})
// when
err := f.Run(context.Background())
assert.Nil(t, err)
for f.StatusUpdateSender.(*p2pStatus).status != peerstatus.Connected {
}
f.store.RemoveLocalPeer("peerId")
f.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId",
Status: pb.EventP2PStatus_NotConnected,
},
},
},
},
})
f.SendPeerUpdate()
err = waitForStatus(f.StatusUpdateSender.(*p2pStatus), peerstatus.NotConnected)
assert.Nil(t, err)
// then
err = f.Close(context.Background())
assert.Nil(t, err)
status := f.StatusUpdateSender.(*p2pStatus)
assert.NotNil(t, status)
assert.Equal(t, peerstatus.NotConnected, status.status)
})
t.Run("connection was not possible, but after a while starts working", func(t *testing.T) {
// given
f := newFixture(t, "spaceId", pb.EventP2PStatus_NotConnected)
// when
err := f.Run(context.Background())
assert.Nil(t, err)
f.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId",
Status: pb.EventP2PStatus_NotPossible,
},
},
},
},
})
f.SendNewStatus(peerstatus.NotPossible)
err = waitForStatus(f.StatusUpdateSender.(*p2pStatus), peerstatus.NotPossible)
assert.Nil(t, err)
f.store.UpdateLocalPeer("peerId", []string{"spaceId"})
f.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId",
Status: pb.EventP2PStatus_Connected,
},
},
},
},
})
f.SendPeerUpdate()
err = waitForStatus(f.StatusUpdateSender.(*p2pStatus), peerstatus.Connected)
assert.Nil(t, err)
// then
err = f.Close(context.Background())
assert.Nil(t, err)
status := f.StatusUpdateSender.(*p2pStatus)
assert.NotNil(t, status)
assert.Equal(t, peerstatus.Connected, status.status)
})
t.Run("no peers were connected, but after a while one is connected", func(t *testing.T) {
// given
f := newFixture(t, "spaceId", pb.EventP2PStatus_NotConnected)
// when
err := f.Run(context.Background())
assert.Nil(t, err)
err = waitForStatus(f.StatusUpdateSender.(*p2pStatus), peerstatus.NotConnected)
assert.Nil(t, err)
f.store.UpdateLocalPeer("peerId", []string{"spaceId"})
f.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: "spaceId",
Status: pb.EventP2PStatus_Connected,
},
},
},
},
})
f.SendPeerUpdate()
err = waitForStatus(f.StatusUpdateSender.(*p2pStatus), peerstatus.Connected)
assert.Nil(t, err)
// then
err = f.Close(context.Background())
assert.Nil(t, err)
status := f.StatusUpdateSender.(*p2pStatus)
assert.NotNil(t, status)
assert.Equal(t, peerstatus.Connected, status.status)
})
}
func newFixture(t *testing.T, spaceId string, initialStatus pb.EventP2PStatusStatus) *fixture {
ctrl := gomock.NewController(t)
a := &app.App{}
ctx := context.Background()
sender := mock_event.NewMockSender(t)
service := mock_nodeconf.NewMockService(ctrl)
service.EXPECT().Name().Return("common.nodeconf").AnyTimes()
store := peerstore.New()
a.Register(testutil.PrepareMock(ctx, a, sender)).
Register(service).
Register(NewObservers()).
Register(store)
err := store.Init(a)
assert.Nil(t, err)
status := NewP2PStatus(spaceId)
f := &fixture{
StatusUpdateSender: status,
sender: sender,
service: service,
store: store,
}
err = f.Init(a)
assert.Nil(t, err)
f.sender.EXPECT().Broadcast(&pb.Event{
Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
SpaceId: spaceId,
Status: initialStatus,
},
},
},
},
}).Maybe()
return f
}
func waitForStatus(statusSender *p2pStatus, expectedStatus peerstatus.Status) error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
if statusSender.status == expectedStatus {
return nil
}
}
}
}

View file

@ -24637,6 +24637,7 @@ Removes document from subscription
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| spaceId | [string](#string) | | |
| status | [Event.P2PStatus.Status](#anytype-Event-P2PStatus-Status) | | |
@ -25037,8 +25038,8 @@ Precondition: user A and user B opened the same block
| Name | Number | Description |
| ---- | ------ | ----------- |
| Possible | 0 | |
| Connected | 1 | |
| Connected | 0 | |
| NotPossible | 1 | |
| NotConnected | 2 | |

4
go.mod
View file

@ -231,7 +231,7 @@ require (
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/pseudomuto/protokit v0.2.1 // indirect
github.com/quic-go/quic-go v0.43.0 // indirect
github.com/quic-go/quic-go v0.43.1 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/rs/zerolog v1.29.0 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
@ -294,3 +294,5 @@ replace github.com/araddon/dateparse => github.com/mehanizm/dateparse v0.0.0-202
replace github.com/multiformats/go-multiaddr => github.com/anyproto/go-multiaddr v0.8.1-0.20221213144344-0b6b93adaec4
replace github.com/gogo/protobuf => github.com/anyproto/protobuf v1.3.3-0.20240201225420-6e325cf0ac38
replace github.com/anyproto/any-sync => ./../any-sync

6
go.sum
View file

@ -89,8 +89,6 @@ github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxB
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/anyproto/any-sync v0.4.14 h1:8AbckYHcy8gRpP/+kULDt2/l3jbaz3Uu5A2mBGTsSGo=
github.com/anyproto/any-sync v0.4.14/go.mod h1:NvsYUYn9HnPC6tnx+VKicGQf78pN3GZFQ28CoDAN27c=
github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580 h1:Ba80IlCCxkZ9H1GF+7vFu/TSpPvbpDCxXJ5ogc4euYc=
github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580/go.mod h1:T/uWAYxrXdaXw64ihI++9RMbKTCpKd/yE9+saARew7k=
github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY=
@ -1257,8 +1255,8 @@ github.com/pseudomuto/protokit v0.2.1 h1:kCYpE3thoR6Esm0CUvd5xbrDTOZPvQPTDeyXpZf
github.com/pseudomuto/protokit v0.2.1/go.mod h1:gt7N5Rz2flBzYafvaxyIxMZC0TTF5jDZfRnw25hAAyo=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/quic-go v0.43.0 h1:sjtsTKWX0dsHpuMJvLxGqoQdtgJnbAPWY+W+5vjYW/g=
github.com/quic-go/quic-go v0.43.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
github.com/quic-go/quic-go v0.43.1 h1:fLiMNfQVe9q2JvSsiXo4fXOEguXHGGl9+6gLp4RPeZQ=
github.com/quic-go/quic-go v0.43.1/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=

View file

@ -5,6 +5,7 @@ package addrs
import (
"net"
"strings"
"github.com/anyproto/anytype-heart/util/slice"
)
@ -26,7 +27,7 @@ func GetInterfacesAddrs() (iAddrs InterfacesAddrs, err error) {
if err != nil {
return
}
iAddrs.Addrs = addrs
iAddrs.Addrs = slice.Filter(addrs, func(addr net.Addr) bool { return !strings.HasPrefix(addr.String(), "127.0.0.1") })
ifaces, err := net.Interfaces()
if err != nil {
return
@ -34,7 +35,7 @@ func GetInterfacesAddrs() (iAddrs InterfacesAddrs, err error) {
iAddrs.Interfaces = ifaces
iAddrs.Interfaces = slice.Filter(iAddrs.Interfaces, func(iface net.Interface) bool {
return iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagMulticast != 0
return iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagMulticast != 0 && iface.Flags&net.FlagLoopback == 0
})
return
}

View file

@ -98,20 +98,20 @@ func (EventStatusThreadSyncStatus) EnumDescriptor() ([]byte, []int) {
type EventP2PStatusStatus int32
const (
EventP2PStatus_Possible EventP2PStatusStatus = 0
EventP2PStatus_Connected EventP2PStatusStatus = 1
EventP2PStatus_Connected EventP2PStatusStatus = 0
EventP2PStatus_NotPossible EventP2PStatusStatus = 1
EventP2PStatus_NotConnected EventP2PStatusStatus = 2
)
var EventP2PStatusStatus_name = map[int32]string{
0: "Possible",
1: "Connected",
0: "Connected",
1: "NotPossible",
2: "NotConnected",
}
var EventP2PStatusStatus_value = map[string]int32{
"Possible": 0,
"Connected": 1,
"Connected": 0,
"NotPossible": 1,
"NotConnected": 2,
}
@ -10794,7 +10794,8 @@ func (m *EventP2PStatus) XXX_DiscardUnknown() {
var xxx_messageInfo_EventP2PStatus proto.InternalMessageInfo
type EventP2PStatusUpdate struct {
Status EventP2PStatusStatus `protobuf:"varint,1,opt,name=status,proto3,enum=anytype.EventP2PStatusStatus" json:"status,omitempty"`
SpaceId string `protobuf:"bytes,1,opt,name=spaceId,proto3" json:"spaceId,omitempty"`
Status EventP2PStatusStatus `protobuf:"varint,2,opt,name=status,proto3,enum=anytype.EventP2PStatusStatus" json:"status,omitempty"`
}
func (m *EventP2PStatusUpdate) Reset() { *m = EventP2PStatusUpdate{} }
@ -10830,11 +10831,18 @@ func (m *EventP2PStatusUpdate) XXX_DiscardUnknown() {
var xxx_messageInfo_EventP2PStatusUpdate proto.InternalMessageInfo
func (m *EventP2PStatusUpdate) GetSpaceId() string {
if m != nil {
return m.SpaceId
}
return ""
}
func (m *EventP2PStatusUpdate) GetStatus() EventP2PStatusStatus {
if m != nil {
return m.Status
}
return EventP2PStatus_Possible
return EventP2PStatus_Connected
}
type ResponseEvent struct {
@ -11264,356 +11272,356 @@ func init() {
func init() { proto.RegisterFile("pb/protos/events.proto", fileDescriptor_a966342d378ae5f5) }
var fileDescriptor_a966342d378ae5f5 = []byte{
// 5569 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7c, 0x49, 0x8c, 0x1c, 0xc9,
0x75, 0x76, 0xd7, 0x5e, 0xf5, 0x9a, 0xdd, 0x2c, 0x06, 0x39, 0x9c, 0x9c, 0x64, 0x4f, 0x0f, 0xa7,
0xb9, 0x6a, 0x86, 0x53, 0xe4, 0x70, 0x6b, 0x8a, 0xc3, 0x21, 0xd9, 0x1b, 0xa7, 0x8b, 0x4b, 0xb3,
0xff, 0x68, 0x92, 0x1a, 0x8d, 0x04, 0x41, 0xd9, 0x99, 0xd1, 0xd5, 0x29, 0x56, 0x67, 0x96, 0x32,
0xb3, 0x9a, 0x6c, 0xe9, 0xb7, 0x6c, 0x78, 0x81, 0x2e, 0x36, 0xec, 0x93, 0x6c, 0xf8, 0x66, 0xc3,
0x06, 0x7c, 0x30, 0x0c, 0x0b, 0xbe, 0xe8, 0x64, 0x18, 0x30, 0x0c, 0x78, 0x3b, 0xc8, 0x3e, 0x18,
0xbe, 0x49, 0x98, 0xb9, 0xf8, 0x62, 0xc0, 0x0b, 0x60, 0xf8, 0x64, 0x18, 0xb1, 0x64, 0x66, 0x44,
0x2e, 0x95, 0x55, 0x9a, 0x91, 0x17, 0x78, 0x4e, 0xdd, 0xf1, 0xe2, 0x7d, 0x5f, 0x6c, 0x2f, 0x5e,
0x44, 0xbc, 0x8c, 0x28, 0x38, 0x3e, 0xd8, 0xbe, 0x38, 0xf0, 0xdc, 0xc0, 0xf5, 0x2f, 0x92, 0x7d,
0xe2, 0x04, 0x7e, 0x87, 0xa5, 0x50, 0xc3, 0x70, 0x0e, 0x82, 0x83, 0x01, 0xd1, 0x4f, 0x0f, 0x9e,
0xf7, 0x2e, 0xf6, 0xed, 0xed, 0x8b, 0x83, 0xed, 0x8b, 0x7b, 0xae, 0x45, 0xfa, 0xa1, 0x3a, 0x4b,
0x08, 0x75, 0x7d, 0xae, 0xe7, 0xba, 0xbd, 0x3e, 0xe1, 0x79, 0xdb, 0xc3, 0x9d, 0x8b, 0x7e, 0xe0,
0x0d, 0xcd, 0x80, 0xe7, 0x2e, 0xfc, 0xdd, 0xf7, 0x4b, 0x50, 0x5b, 0xa3, 0xf4, 0xe8, 0x32, 0x34,
0xf7, 0x88, 0xef, 0x1b, 0x3d, 0xe2, 0x6b, 0xa5, 0x93, 0x95, 0xf3, 0xd3, 0x97, 0x8f, 0x77, 0x44,
0x51, 0x1d, 0xa6, 0xd1, 0x79, 0xc4, 0xb3, 0x71, 0xa4, 0x87, 0xe6, 0xa0, 0x65, 0xba, 0x4e, 0x40,
0x5e, 0x06, 0x5d, 0x4b, 0x2b, 0x9f, 0x2c, 0x9d, 0x6f, 0xe1, 0x58, 0x80, 0xae, 0x42, 0xcb, 0x76,
0xec, 0xc0, 0x36, 0x02, 0xd7, 0xd3, 0x2a, 0x27, 0x4b, 0x0a, 0x25, 0xab, 0x64, 0x67, 0xc9, 0x34,
0xdd, 0xa1, 0x13, 0xe0, 0x58, 0x11, 0x69, 0xd0, 0x08, 0x3c, 0xc3, 0x24, 0x5d, 0x4b, 0xab, 0x32,
0xc6, 0x30, 0xa9, 0xff, 0xed, 0x05, 0x68, 0x88, 0x3a, 0xa0, 0x3b, 0x30, 0x6d, 0x70, 0xec, 0xd6,
0xae, 0xfb, 0x42, 0x2b, 0x31, 0xf6, 0x13, 0x89, 0x0a, 0x0b, 0xf6, 0x0e, 0x55, 0x59, 0x9f, 0xc2,
0x32, 0x02, 0x75, 0x61, 0x56, 0x24, 0x57, 0x49, 0x60, 0xd8, 0x7d, 0x5f, 0xfb, 0x0b, 0x4e, 0x32,
0x9f, 0x43, 0x22, 0xd4, 0xd6, 0xa7, 0x70, 0x02, 0x88, 0xbe, 0x0c, 0x47, 0x85, 0x64, 0xc5, 0x75,
0x76, 0xec, 0xde, 0xd3, 0x81, 0x65, 0x04, 0x44, 0xfb, 0x4b, 0xce, 0x77, 0x3a, 0x87, 0x8f, 0xeb,
0x76, 0xb8, 0xf2, 0xfa, 0x14, 0xce, 0xe2, 0x40, 0xf7, 0x60, 0x46, 0x88, 0x05, 0xe9, 0x5f, 0x71,
0xd2, 0xd7, 0x73, 0x48, 0x23, 0x36, 0x15, 0x86, 0xbe, 0x02, 0xc7, 0x84, 0xe0, 0xa1, 0xed, 0x3c,
0x5f, 0xd9, 0x35, 0xfa, 0x7d, 0xe2, 0xf4, 0x88, 0xf6, 0xd7, 0xa3, 0xeb, 0xa8, 0x28, 0xaf, 0x4f,
0xe1, 0x4c, 0x12, 0xf4, 0x18, 0xda, 0xee, 0xf6, 0x37, 0x88, 0x19, 0x76, 0xc8, 0x16, 0x09, 0xb4,
0x36, 0xe3, 0x7d, 0x33, 0xc1, 0xfb, 0x98, 0xa9, 0x85, 0x5d, 0xd9, 0xd9, 0x22, 0xc1, 0xfa, 0x14,
0x4e, 0x81, 0xd1, 0x53, 0x40, 0x8a, 0x6c, 0x69, 0x8f, 0x38, 0x96, 0x76, 0x99, 0x51, 0x9e, 0x1a,
0x4d, 0xc9, 0x54, 0xd7, 0xa7, 0x70, 0x06, 0x41, 0x8a, 0xf6, 0xa9, 0xe3, 0x93, 0x40, 0xbb, 0x32,
0x0e, 0x2d, 0x53, 0x4d, 0xd1, 0x32, 0x29, 0xed, 0x5b, 0x2e, 0xc5, 0xa4, 0x6f, 0x04, 0xb6, 0xeb,
0x88, 0xfa, 0x5e, 0x65, 0xc4, 0x67, 0xb2, 0x89, 0x23, 0xdd, 0xa8, 0xc6, 0x99, 0x24, 0xe8, 0x6b,
0xf0, 0x4a, 0x42, 0x8e, 0xc9, 0x9e, 0xbb, 0x4f, 0xb4, 0x6b, 0x8c, 0xfd, 0x6c, 0x11, 0x3b, 0xd7,
0x5e, 0x9f, 0xc2, 0xd9, 0x34, 0x68, 0x19, 0x0e, 0x85, 0x19, 0x8c, 0xf6, 0x3a, 0xa3, 0x9d, 0xcb,
0xa3, 0x15, 0x64, 0x0a, 0x46, 0xae, 0xa3, 0x1f, 0x78, 0xb6, 0xc9, 0xf8, 0xa9, 0x11, 0x2c, 0x8e,
0xae, 0x63, 0xac, 0x2c, 0x2c, 0x21, 0x9b, 0x06, 0x61, 0x38, 0xec, 0x0f, 0xb7, 0x7d, 0xd3, 0xb3,
0x07, 0x54, 0xb6, 0x64, 0x59, 0xda, 0xad, 0x51, 0xcc, 0x5b, 0x92, 0x72, 0x67, 0xc9, 0xa2, 0x9d,
0x9b, 0x24, 0x40, 0x5f, 0x01, 0x24, 0x8b, 0x44, 0xeb, 0xdf, 0x67, 0xb4, 0x5f, 0x18, 0x83, 0x36,
0xea, 0x8a, 0x0c, 0x1a, 0x64, 0xc0, 0x31, 0x59, 0xba, 0xe9, 0xfa, 0x36, 0xfd, 0xab, 0xdd, 0x66,
0xf4, 0x6f, 0x8f, 0x41, 0x1f, 0x42, 0xa8, 0x5d, 0x64, 0x51, 0x25, 0x8b, 0x58, 0xa1, 0xb3, 0x92,
0x78, 0xbe, 0x76, 0x67, 0xec, 0x22, 0x42, 0x48, 0xb2, 0x88, 0x50, 0x9e, 0xec, 0xa2, 0x0f, 0x3c,
0x77, 0x38, 0xf0, 0xb5, 0xbb, 0x63, 0x77, 0x11, 0x07, 0x24, 0xbb, 0x88, 0x4b, 0xd1, 0x75, 0x68,
0x6e, 0xf7, 0x5d, 0xf3, 0x39, 0x1d, 0xcc, 0x32, 0xa3, 0xd4, 0x12, 0x94, 0xcb, 0x34, 0x5b, 0x0c,
0x5f, 0xa4, 0x4b, 0xfd, 0x3e, 0xfb, 0x7f, 0x95, 0xf4, 0x49, 0x40, 0xc4, 0xaa, 0x72, 0x22, 0x13,
0xca, 0x55, 0xa8, 0xdf, 0x97, 0x10, 0x68, 0x15, 0xa6, 0x77, 0xec, 0x3e, 0xf1, 0x9f, 0x0e, 0xfa,
0xae, 0xc1, 0x97, 0x98, 0xe9, 0xcb, 0x27, 0x33, 0x09, 0xee, 0xc5, 0x7a, 0x94, 0x45, 0x82, 0xa1,
0xdb, 0xd0, 0xda, 0x33, 0xbc, 0xe7, 0x7e, 0xd7, 0xd9, 0x71, 0xb5, 0x5a, 0xe6, 0xba, 0xc1, 0x39,
0x1e, 0x85, 0x5a, 0xeb, 0x53, 0x38, 0x86, 0xd0, 0xd5, 0x87, 0x55, 0x6a, 0x8b, 0x04, 0xf7, 0x6c,
0xd2, 0xb7, 0x7c, 0xad, 0xce, 0x48, 0xde, 0xc8, 0x24, 0xd9, 0x22, 0x41, 0x87, 0xab, 0xd1, 0xd5,
0x47, 0x05, 0xa2, 0x0f, 0xe1, 0x68, 0x28, 0x59, 0xd9, 0xb5, 0xfb, 0x96, 0x47, 0x9c, 0xae, 0xe5,
0x6b, 0x8d, 0x4c, 0xc7, 0x1e, 0xf3, 0x49, 0xba, 0x74, 0xf1, 0xc9, 0xa0, 0xa0, 0x8e, 0x2d, 0x14,
0xcb, 0x53, 0x52, 0x6b, 0x66, 0x3a, 0xb6, 0x98, 0x5a, 0x56, 0xa6, 0xd6, 0x95, 0x45, 0x82, 0x2c,
0x78, 0x35, 0x94, 0x2f, 0x1b, 0xe6, 0xf3, 0x9e, 0xe7, 0x0e, 0x1d, 0x6b, 0xc5, 0xed, 0xbb, 0x9e,
0xd6, 0x62, 0xfc, 0xe7, 0x73, 0xf9, 0x13, 0xfa, 0xeb, 0x53, 0x38, 0x8f, 0x0a, 0xad, 0xc0, 0xa1,
0x30, 0xeb, 0x09, 0x79, 0x19, 0x68, 0x90, 0xb9, 0x7a, 0xc6, 0xd4, 0x54, 0x89, 0xfa, 0x37, 0x19,
0x24, 0x93, 0x50, 0x93, 0xd0, 0xa6, 0x0b, 0x48, 0xa8, 0x92, 0x4c, 0x42, 0xd3, 0x32, 0x09, 0x5d,
0x3d, 0xb5, 0x99, 0x02, 0x12, 0xaa, 0x24, 0x93, 0xd0, 0x34, 0x5d, 0x69, 0xa3, 0x96, 0xba, 0xee,
0x73, 0x6a, 0x4f, 0xda, 0x6c, 0xe6, 0x4a, 0x2b, 0xf5, 0x96, 0x50, 0xa4, 0x2b, 0x6d, 0x12, 0x4c,
0xf7, 0x17, 0xa1, 0x6c, 0xa9, 0x6f, 0xf7, 0x1c, 0xed, 0xf0, 0x08, 0x5b, 0xa6, 0x6c, 0x4c, 0x8b,
0xee, 0x2f, 0x14, 0x18, 0xba, 0x2b, 0xa6, 0xe5, 0x16, 0x09, 0x56, 0xed, 0x7d, 0xed, 0x48, 0xe6,
0x2a, 0x12, 0xb3, 0xac, 0xda, 0xfb, 0xd1, 0xbc, 0xe4, 0x10, 0xb9, 0x69, 0xe1, 0x1a, 0xa5, 0xbd,
0x52, 0xd0, 0xb4, 0x50, 0x51, 0x6e, 0x5a, 0x28, 0x93, 0x9b, 0xf6, 0xd0, 0x08, 0xc8, 0x4b, 0xed,
0xb5, 0x82, 0xa6, 0x31, 0x2d, 0xb9, 0x69, 0x4c, 0x40, 0x57, 0xb7, 0x50, 0xf0, 0x8c, 0x78, 0x81,
0x6d, 0x1a, 0x7d, 0xde, 0x55, 0xa7, 0x33, 0xd7, 0xa0, 0x98, 0x4f, 0xd1, 0xa6, 0xab, 0x5b, 0x26,
0x8d, 0xdc, 0xf0, 0x27, 0xc6, 0x76, 0x9f, 0x60, 0xf7, 0x85, 0x76, 0xa6, 0xa0, 0xe1, 0xa1, 0xa2,
0xdc, 0xf0, 0x50, 0x26, 0xfb, 0x96, 0x2f, 0xd9, 0x56, 0x8f, 0x04, 0xda, 0xf9, 0x02, 0xdf, 0xc2,
0xd5, 0x64, 0xdf, 0xc2, 0x25, 0x91, 0x07, 0x58, 0x35, 0x02, 0x63, 0xdf, 0x26, 0x2f, 0x9e, 0xd9,
0xe4, 0x05, 0x5d, 0xd8, 0x8f, 0x8e, 0xf0, 0x00, 0xa1, 0x6e, 0x47, 0x28, 0x47, 0x1e, 0x20, 0x41,
0x12, 0x79, 0x00, 0x59, 0x2e, 0xdc, 0xfa, 0xb1, 0x11, 0x1e, 0x40, 0xe1, 0x8f, 0x7c, 0x7c, 0x1e,
0x15, 0x32, 0xe0, 0x78, 0x2a, 0xeb, 0xb1, 0x67, 0x11, 0x4f, 0x7b, 0x9d, 0x15, 0x72, 0xae, 0xb8,
0x10, 0xa6, 0xbe, 0x3e, 0x85, 0x73, 0x88, 0x52, 0x45, 0x6c, 0xb9, 0x43, 0xcf, 0x24, 0xb4, 0x9f,
0x4e, 0x8d, 0x53, 0x44, 0xa4, 0x9e, 0x2a, 0x22, 0xca, 0x41, 0xfb, 0xf0, 0x7a, 0x94, 0x43, 0x0b,
0x66, 0xab, 0x28, 0x2b, 0x5d, 0x9c, 0x0b, 0xce, 0xb2, 0x92, 0x3a, 0xa3, 0x4b, 0x4a, 0xa2, 0xd6,
0xa7, 0xf0, 0x68, 0x5a, 0x74, 0x00, 0xf3, 0x8a, 0x02, 0x5f, 0xe7, 0xe5, 0x82, 0xcf, 0xb1, 0x82,
0x2f, 0x8e, 0x2e, 0x38, 0x05, 0x5b, 0x9f, 0xc2, 0x05, 0xc4, 0x68, 0x00, 0x27, 0x94, 0xce, 0x08,
0x27, 0xb6, 0x30, 0x91, 0xff, 0xcf, 0xca, 0xbd, 0x30, 0xba, 0x5c, 0x15, 0xb3, 0x3e, 0x85, 0x47,
0x51, 0xa2, 0x1e, 0x68, 0x99, 0xd9, 0x74, 0x24, 0xbf, 0x9d, 0xb9, 0xed, 0xc9, 0x29, 0x8e, 0x8f,
0x65, 0x2e, 0x59, 0xa6, 0xe5, 0x8b, 0xee, 0xfc, 0x99, 0x71, 0x2d, 0x3f, 0xea, 0xc7, 0x3c, 0x2a,
0x65, 0xec, 0x68, 0xd6, 0x13, 0xc3, 0xeb, 0x91, 0x80, 0x77, 0x74, 0xd7, 0xa2, 0x8d, 0xfa, 0xce,
0x38, 0x63, 0x97, 0x82, 0x29, 0x63, 0x97, 0x49, 0x8c, 0x7c, 0x98, 0x53, 0x34, 0xba, 0xfe, 0x8a,
0xdb, 0xef, 0x13, 0x33, 0xec, 0xcd, 0x9f, 0x65, 0x05, 0xbf, 0x33, 0xba, 0xe0, 0x04, 0x68, 0x7d,
0x0a, 0x8f, 0x24, 0x4d, 0xb5, 0xf7, 0x71, 0xdf, 0x4a, 0xd8, 0x8c, 0x36, 0x96, 0xad, 0x26, 0x61,
0xa9, 0xf6, 0xa6, 0x34, 0x52, 0xb6, 0x2a, 0x69, 0xd0, 0xe6, 0xbe, 0x3a, 0x8e, 0xad, 0xaa, 0x98,
0x94, 0xad, 0xaa, 0xd9, 0x74, 0x75, 0x1b, 0xfa, 0xc4, 0x63, 0x1c, 0xf7, 0x5d, 0xdb, 0xd1, 0xde,
0xc8, 0x5c, 0xdd, 0x9e, 0xfa, 0xc4, 0x13, 0x05, 0x51, 0x2d, 0xba, 0xba, 0x29, 0x30, 0x85, 0xe7,
0x21, 0xd9, 0x09, 0xb4, 0x93, 0x45, 0x3c, 0x54, 0x4b, 0xe1, 0xa1, 0x02, 0xba, 0x52, 0x44, 0x82,
0x2d, 0x42, 0x47, 0x05, 0x1b, 0x4e, 0x8f, 0x68, 0x6f, 0x66, 0xae, 0x14, 0x12, 0x9d, 0xa4, 0x4c,
0x57, 0x8a, 0x2c, 0x12, 0x7a, 0x70, 0x8f, 0xe4, 0x74, 0x47, 0xc6, 0xa9, 0x17, 0x32, 0x0f, 0xee,
0x12, 0x75, 0xa4, 0x4a, 0xcf, 0x20, 0x69, 0x02, 0xf4, 0x05, 0xa8, 0x0e, 0x6c, 0xa7, 0xa7, 0x59,
0x8c, 0xe8, 0x68, 0x82, 0x68, 0xd3, 0x76, 0x7a, 0xeb, 0x53, 0x98, 0xa9, 0xa0, 0x5b, 0x00, 0x03,
0xcf, 0x35, 0x89, 0xef, 0x6f, 0x90, 0x17, 0x1a, 0x61, 0x00, 0x3d, 0x09, 0xe0, 0x0a, 0x9d, 0x0d,
0x42, 0xd7, 0x65, 0x49, 0x1f, 0xad, 0xc1, 0x8c, 0x48, 0x89, 0x59, 0xbe, 0x93, 0xb9, 0xf9, 0x0b,
0x09, 0xe2, 0x20, 0x8e, 0x82, 0xa2, 0x67, 0x1f, 0x21, 0x58, 0x75, 0x1d, 0xa2, 0xf5, 0x32, 0xcf,
0x3e, 0x21, 0x09, 0x55, 0xa1, 0x7b, 0x2c, 0x09, 0x41, 0x0f, 0xfb, 0xc1, 0xae, 0x47, 0x0c, 0x6b,
0x2b, 0x30, 0x82, 0xa1, 0xaf, 0x39, 0x99, 0xdb, 0x34, 0x9e, 0xd9, 0x79, 0xc2, 0x34, 0xe9, 0x16,
0x54, 0xc6, 0xa0, 0x0d, 0x68, 0xd3, 0x83, 0xd0, 0x43, 0x7b, 0xcf, 0x0e, 0x30, 0x31, 0xcc, 0x5d,
0x62, 0x69, 0x6e, 0xe6, 0x21, 0x8a, 0x6e, 0x7b, 0x3b, 0xb2, 0x1e, 0xdd, 0xad, 0x24, 0xb1, 0x68,
0x1d, 0x66, 0xa9, 0x6c, 0x6b, 0x60, 0x98, 0xe4, 0xa9, 0x6f, 0xf4, 0x88, 0x36, 0xc8, 0xb4, 0x40,
0xc6, 0x16, 0x6b, 0xd1, 0xcd, 0x8a, 0x8a, 0x0b, 0x99, 0x1e, 0xba, 0xa6, 0xd1, 0xe7, 0x4c, 0xdf,
0xcc, 0x67, 0x8a, 0xb5, 0x42, 0xa6, 0x58, 0xa2, 0xb4, 0x91, 0xf7, 0xbd, 0xa5, 0xed, 0x17, 0xb4,
0x51, 0xe8, 0x29, 0x6d, 0x14, 0x32, 0xca, 0xe7, 0xb8, 0x81, 0xbd, 0x63, 0x9b, 0x62, 0xfe, 0x3a,
0x96, 0xe6, 0x65, 0xf2, 0x6d, 0x48, 0x6a, 0x9d, 0x2d, 0x1e, 0x18, 0x4a, 0x61, 0xd1, 0x13, 0x40,
0xb2, 0x4c, 0x18, 0x95, 0xcf, 0x18, 0x17, 0x46, 0x31, 0x46, 0x96, 0x95, 0x81, 0xa7, 0xb5, 0x1c,
0x18, 0x07, 0xf4, 0x78, 0xbb, 0xec, 0xb9, 0x86, 0x65, 0x1a, 0x7e, 0xa0, 0x05, 0x99, 0xb5, 0xdc,
0xe4, 0x6a, 0x9d, 0x48, 0x8f, 0xd6, 0x32, 0x89, 0xa5, 0x7c, 0x7b, 0x64, 0x6f, 0x9b, 0x78, 0xfe,
0xae, 0x3d, 0x10, 0x75, 0x1c, 0x66, 0xf2, 0x3d, 0x8a, 0xd4, 0xe2, 0x1a, 0xa6, 0xb0, 0xe8, 0x01,
0x1c, 0x1e, 0x5c, 0x1e, 0x70, 0x33, 0x14, 0x74, 0x2f, 0x32, 0x37, 0xb6, 0x9b, 0x97, 0x37, 0x85,
0x0d, 0x47, 0x6c, 0x49, 0xe4, 0x72, 0x03, 0x6a, 0xfb, 0x46, 0x7f, 0x48, 0xf4, 0xef, 0xd7, 0xa0,
0x21, 0xc2, 0x9d, 0xfa, 0x06, 0x54, 0x59, 0x6c, 0xf8, 0x18, 0xd4, 0x6c, 0xc7, 0x22, 0x2f, 0x59,
0x58, 0xb9, 0x86, 0x79, 0x02, 0x5d, 0x82, 0x86, 0x08, 0x7f, 0x8a, 0x88, 0x45, 0x5e, 0x30, 0x3b,
0x54, 0xd3, 0x3f, 0x82, 0x46, 0x18, 0x23, 0x9e, 0x83, 0xd6, 0xc0, 0x73, 0xa9, 0x65, 0x74, 0x2d,
0x46, 0xdb, 0xc2, 0xb1, 0x00, 0xbd, 0x0b, 0x0d, 0x4b, 0x44, 0xa1, 0x39, 0xf5, 0xab, 0x1d, 0x1e,
0xb6, 0xef, 0x84, 0x61, 0xfb, 0xce, 0x16, 0x0b, 0xdb, 0xe3, 0x50, 0x4f, 0xff, 0xb9, 0x12, 0xd4,
0x79, 0xa8, 0x58, 0xdf, 0x87, 0xba, 0xe8, 0xa2, 0x6b, 0x50, 0x37, 0x99, 0x4c, 0x4b, 0x86, 0x89,
0x95, 0x1a, 0x8a, 0xd8, 0x33, 0x16, 0xca, 0x14, 0xe6, 0x73, 0x8f, 0x50, 0x1e, 0x09, 0xe3, 0x3d,
0x88, 0x85, 0xf2, 0x7f, 0x5b, 0xb9, 0xff, 0x51, 0x82, 0x19, 0x35, 0x02, 0x3d, 0x07, 0x2d, 0x33,
0x8a, 0x69, 0x8b, 0xde, 0x35, 0xa5, 0xf8, 0x34, 0x98, 0x7d, 0x9b, 0x38, 0x01, 0x8b, 0xd6, 0x94,
0x33, 0x37, 0x01, 0x99, 0x11, 0xef, 0xce, 0x4a, 0x04, 0xc3, 0x12, 0x85, 0xfe, 0x1d, 0x80, 0x38,
0x07, 0x9d, 0x8c, 0xdc, 0xf2, 0x86, 0xb1, 0x17, 0x16, 0x2f, 0x8b, 0x24, 0x8d, 0x4d, 0x23, 0xd8,
0x15, 0x1f, 0x4a, 0x64, 0x11, 0xba, 0x00, 0x47, 0x7c, 0xbb, 0xe7, 0x18, 0xc1, 0xd0, 0x23, 0xcf,
0x88, 0x67, 0xef, 0xd8, 0xc4, 0x62, 0xc1, 0xad, 0x26, 0x4e, 0x67, 0xe8, 0xff, 0xd4, 0x84, 0x3a,
0xdf, 0x6e, 0xe9, 0xff, 0x56, 0x8e, 0x6c, 0x4c, 0xff, 0xd3, 0x12, 0xd4, 0x78, 0xd4, 0x78, 0x16,
0xca, 0x76, 0x68, 0x66, 0x65, 0xdb, 0x42, 0xf7, 0x64, 0xfb, 0xaa, 0x64, 0xec, 0x45, 0xb2, 0xa2,
0xe8, 0x9d, 0x07, 0xe4, 0xe0, 0x19, 0x9d, 0x23, 0x91, 0xd1, 0xa1, 0xe3, 0x50, 0xf7, 0x87, 0xdb,
0x5d, 0xcb, 0xd7, 0x2a, 0x27, 0x2b, 0xe7, 0x5b, 0x58, 0xa4, 0xf4, 0xfb, 0xd0, 0x0c, 0x95, 0x51,
0x1b, 0x2a, 0xcf, 0xc9, 0x81, 0x28, 0x9c, 0xfe, 0x8b, 0x2e, 0x88, 0xb9, 0x16, 0x4d, 0x9b, 0xa4,
0x6d, 0xf3, 0x52, 0xc4, 0x84, 0xfc, 0x3a, 0x54, 0xe8, 0x06, 0x27, 0xd9, 0x84, 0xc9, 0xa7, 0x48,
0x6e, 0x6d, 0x57, 0xa0, 0xc6, 0x23, 0xf7, 0xc9, 0x32, 0x10, 0x54, 0x9f, 0x93, 0x03, 0xde, 0x47,
0x2d, 0xcc, 0xfe, 0xcf, 0x25, 0xf9, 0x93, 0x0a, 0x1c, 0x92, 0xc3, 0x9d, 0xfa, 0x1a, 0x54, 0x96,
0xac, 0x74, 0xd7, 0x6b, 0xd0, 0x30, 0x76, 0x02, 0xe2, 0x45, 0x1f, 0xc8, 0xc2, 0x24, 0xf5, 0x32,
0x8c, 0x8b, 0x8d, 0x73, 0x0b, 0xf3, 0x84, 0xde, 0x81, 0xba, 0x88, 0x22, 0x27, 0x99, 0x22, 0xfd,
0xb2, 0xac, 0x7f, 0x1f, 0x9a, 0x51, 0x50, 0xf8, 0xd3, 0x96, 0xed, 0x41, 0x33, 0x8a, 0xfe, 0x1e,
0x83, 0x5a, 0xe0, 0x06, 0x46, 0x9f, 0xd1, 0x55, 0x30, 0x4f, 0xd0, 0x89, 0xe6, 0x90, 0x97, 0xc1,
0x4a, 0xe4, 0x05, 0x2b, 0x38, 0x16, 0x70, 0x27, 0x47, 0xf6, 0x79, 0x6e, 0x85, 0xe7, 0x46, 0x82,
0xb8, 0xcc, 0xaa, 0x5c, 0xe6, 0x01, 0xd4, 0x45, 0x48, 0x38, 0xca, 0x2f, 0x49, 0xf9, 0x68, 0x09,
0x6a, 0x3d, 0x9a, 0x2f, 0x46, 0xfd, 0xed, 0x84, 0x8b, 0xe0, 0x3b, 0xbd, 0x15, 0xd7, 0x09, 0xa8,
0x19, 0xab, 0x27, 0x5d, 0xcc, 0x91, 0x74, 0x08, 0x3d, 0x1e, 0xdf, 0xe7, 0x33, 0x4a, 0xa4, 0xf4,
0xdf, 0x2d, 0x41, 0x2b, 0xfa, 0x1e, 0xa2, 0x7f, 0x94, 0x37, 0x79, 0x96, 0x60, 0xc6, 0x13, 0x5a,
0xd4, 0x3b, 0x84, 0x53, 0xe8, 0x44, 0xa2, 0x26, 0x58, 0xd2, 0xc1, 0x2a, 0x42, 0xbf, 0x95, 0x3b,
0xa8, 0x0b, 0x70, 0x28, 0x54, 0x7d, 0x10, 0x9b, 0x9e, 0x22, 0xd3, 0xf5, 0x08, 0xdd, 0x86, 0x8a,
0x6d, 0xf1, 0xcf, 0xb3, 0x2d, 0x4c, 0xff, 0xd5, 0x77, 0xe0, 0x90, 0x1c, 0x56, 0xd5, 0x9f, 0x65,
0xcf, 0x9e, 0x3b, 0xb4, 0x18, 0x29, 0x84, 0x5b, 0x4e, 0xec, 0x1d, 0xc3, 0x26, 0xc4, 0x2a, 0x58,
0x01, 0xe8, 0xbf, 0x69, 0x42, 0x8d, 0xf5, 0xb5, 0x7e, 0x85, 0xdb, 0xf9, 0x05, 0xa8, 0xb3, 0xf3,
0x49, 0xf8, 0xb1, 0xf8, 0x58, 0xd6, 0xc0, 0x60, 0xa1, 0xa3, 0xaf, 0xc0, 0xb4, 0x14, 0x4d, 0xa7,
0x86, 0xc9, 0x32, 0xa2, 0xc1, 0x0e, 0x93, 0x48, 0x87, 0x26, 0x5d, 0x13, 0x85, 0x9f, 0xa4, 0xcd,
0x8c, 0xd2, 0xfa, 0x69, 0xa8, 0x8b, 0xf3, 0x96, 0x2e, 0xbe, 0x1e, 0x74, 0xa3, 0xce, 0x88, 0xd2,
0xfa, 0x57, 0xa1, 0x15, 0x05, 0xdd, 0xd1, 0x63, 0x38, 0x24, 0x82, 0xee, 0xfc, 0xcc, 0x40, 0x95,
0x67, 0x0b, 0x8c, 0x88, 0x1e, 0x10, 0x58, 0xdc, 0xbe, 0xf3, 0xe4, 0x60, 0x40, 0xb0, 0x42, 0xa0,
0xff, 0xd2, 0x79, 0xd6, 0xc1, 0xfa, 0x00, 0x9a, 0x51, 0xa4, 0x31, 0xd9, 0xd9, 0x8b, 0xdc, 0x03,
0x96, 0x0b, 0xc3, 0xe4, 0x1c, 0x4f, 0xfd, 0x2c, 0x73, 0x94, 0xfa, 0x09, 0xa8, 0x3c, 0x20, 0x07,
0x74, 0x22, 0x70, 0x7f, 0x29, 0x26, 0x02, 0xf7, 0x8b, 0x5d, 0xa8, 0x8b, 0x88, 0x7f, 0xb2, 0xbc,
0x8b, 0x50, 0xdf, 0xe1, 0x1f, 0x11, 0x0a, 0x3c, 0xa3, 0x50, 0xd3, 0xef, 0xc0, 0xb4, 0x1c, 0xe7,
0x4f, 0xf2, 0x9d, 0x84, 0x69, 0x53, 0xfa, 0x92, 0xc0, 0x87, 0x41, 0x16, 0xe9, 0x44, 0xb5, 0xba,
0x14, 0xc3, 0x5a, 0xa6, 0xb9, 0xbd, 0x99, 0xd9, 0xed, 0x23, 0x8c, 0xee, 0x01, 0x1c, 0x4e, 0x06,
0xf4, 0x93, 0x25, 0x9d, 0x87, 0xc3, 0xdb, 0x89, 0xcf, 0x07, 0xdc, 0xd5, 0x25, 0xc5, 0x7a, 0x17,
0x6a, 0x3c, 0xe0, 0x9a, 0xa4, 0xb8, 0x04, 0x35, 0x83, 0x05, 0x74, 0x29, 0x70, 0x56, 0x3a, 0xd6,
0xc9, 0xb5, 0x64, 0x50, 0xcc, 0x15, 0x75, 0x1b, 0x66, 0xd4, 0x18, 0x6e, 0x92, 0x72, 0x1d, 0x66,
0xf6, 0x95, 0x58, 0x31, 0xa7, 0x5e, 0xc8, 0xa4, 0x56, 0xa8, 0xb0, 0x0a, 0xd4, 0x7f, 0xbe, 0x0e,
0x55, 0xf6, 0x11, 0x22, 0x59, 0xc4, 0x75, 0xa8, 0x06, 0xe4, 0x65, 0xb8, 0x15, 0x5d, 0x18, 0xf9,
0x45, 0x83, 0x9f, 0x84, 0x99, 0x3e, 0xfa, 0x22, 0xd4, 0xfc, 0xe0, 0xa0, 0x1f, 0x7e, 0x3a, 0x3b,
0x35, 0x1a, 0xb8, 0x45, 0x55, 0x31, 0x47, 0x50, 0x28, 0x9b, 0x0b, 0xe2, 0xa3, 0x59, 0x01, 0x94,
0x4d, 0x42, 0xcc, 0x11, 0xe8, 0x0e, 0x34, 0xcc, 0x5d, 0x62, 0x3e, 0x27, 0x96, 0xf8, 0x5a, 0x76,
0x66, 0x34, 0x78, 0x85, 0x2b, 0xe3, 0x10, 0x45, 0xcb, 0x36, 0xd9, 0xe8, 0xd6, 0xc7, 0x29, 0x9b,
0x8d, 0x38, 0xe6, 0x08, 0xb4, 0x06, 0x2d, 0xdb, 0x74, 0x9d, 0xb5, 0x3d, 0xf7, 0x1b, 0xb6, 0xf8,
0x2c, 0x76, 0x6e, 0x34, 0xbc, 0x1b, 0xaa, 0xe3, 0x18, 0x19, 0xd2, 0x74, 0xf7, 0xe8, 0xc9, 0xb2,
0x39, 0x2e, 0x0d, 0x53, 0xc7, 0x31, 0x52, 0x9f, 0x13, 0xe3, 0x99, 0x3d, 0xc9, 0xef, 0x41, 0x8d,
0x75, 0x39, 0x7a, 0x5f, 0xce, 0x9e, 0x95, 0x4a, 0xca, 0xf5, 0x58, 0x62, 0xa8, 0x22, 0x1e, 0xd6,
0xff, 0x2a, 0xcf, 0xf4, 0x38, 0x3c, 0x62, 0xdc, 0x38, 0xcf, 0x1b, 0xd0, 0x10, 0x43, 0xa1, 0x56,
0xb8, 0x19, 0x2a, 0xbc, 0x0e, 0x35, 0x3e, 0x31, 0xb3, 0xdb, 0xf3, 0x26, 0xb4, 0xa2, 0xce, 0x1c,
0xad, 0xc2, 0x7a, 0x27, 0x47, 0xe5, 0xbb, 0x65, 0xa8, 0xf1, 0x8f, 0x31, 0x69, 0x57, 0x2b, 0xcf,
0x82, 0x53, 0xa3, 0xbf, 0xed, 0xc8, 0xd3, 0xe0, 0x1e, 0x3b, 0x8f, 0xd1, 0xfd, 0x77, 0x74, 0x37,
0xe9, 0x7c, 0x01, 0x7a, 0x33, 0xd4, 0xc7, 0x31, 0xb4, 0x60, 0x38, 0x1f, 0x43, 0x2b, 0x42, 0xa1,
0x65, 0x75, 0x48, 0x2f, 0x8c, 0x1c, 0x8a, 0x64, 0x91, 0x82, 0xf0, 0x7b, 0x25, 0xa8, 0xac, 0xda,
0xfb, 0xa9, 0x7e, 0xb8, 0x11, 0xce, 0xea, 0x22, 0x77, 0xb0, 0x6a, 0xef, 0x2b, 0x93, 0x5a, 0x5f,
0x0b, 0x2d, 0xee, 0x96, 0x5a, 0xbd, 0xb3, 0xa3, 0x37, 0x5a, 0x31, 0x0d, 0xaf, 0xd8, 0xaf, 0x36,
0xa0, 0xca, 0xbe, 0x73, 0x66, 0xf9, 0xa9, 0x83, 0x41, 0x71, 0xc5, 0x58, 0x24, 0x85, 0x2d, 0xb8,
0x4c, 0x9f, 0xfb, 0x29, 0x23, 0x28, 0xf6, 0x53, 0x3c, 0x30, 0x44, 0x55, 0x31, 0x47, 0xd0, 0x22,
0xf7, 0xec, 0x3d, 0x22, 0xdc, 0x54, 0x41, 0x91, 0x8f, 0xec, 0x3d, 0x82, 0x99, 0x3e, 0xc5, 0xed,
0x1a, 0xfe, 0xae, 0xf0, 0x50, 0x05, 0xb8, 0x75, 0xc3, 0xdf, 0xc5, 0x4c, 0x9f, 0xe2, 0x1c, 0x7a,
0xf2, 0xab, 0x8f, 0x83, 0xa3, 0x07, 0x42, 0xcc, 0xf4, 0x29, 0xce, 0xb7, 0xbf, 0x45, 0x84, 0x4f,
0x2a, 0xc0, 0x6d, 0xd9, 0xdf, 0x22, 0x98, 0xe9, 0xc7, 0x2e, 0xbc, 0x39, 0x5e, 0xd7, 0x48, 0x2e,
0xfc, 0x09, 0xcc, 0x06, 0x4a, 0xb4, 0x5e, 0x7c, 0x6c, 0xbf, 0x50, 0x30, 0x2e, 0x0a, 0x06, 0x27,
0x38, 0xe8, 0x24, 0x60, 0xe7, 0xdc, 0xec, 0x49, 0xf0, 0x3a, 0xd4, 0xbe, 0x64, 0x5b, 0xc1, 0xae,
0x9a, 0x5d, 0x53, 0x5c, 0x1e, 0x1d, 0xb6, 0x89, 0x5c, 0x9e, 0x3c, 0xea, 0x9c, 0x67, 0x15, 0xaa,
0xd4, 0x7c, 0x26, 0xb3, 0xe3, 0xd8, 0xea, 0x3e, 0x95, 0x03, 0x96, 0x3b, 0x9a, 0xf3, 0xcc, 0x41,
0x95, 0x5a, 0x48, 0x4e, 0x97, 0xcc, 0x41, 0x95, 0xda, 0x5d, 0x7e, 0x2e, 0x1d, 0x6d, 0x35, 0xb7,
0x12, 0xe6, 0x9e, 0x85, 0x59, 0x75, 0x38, 0x72, 0x58, 0xfe, 0xb8, 0x01, 0x55, 0x76, 0x69, 0x20,
0x39, 0x23, 0xff, 0x1f, 0xcc, 0xf0, 0xf1, 0x5b, 0x16, 0x5b, 0xf0, 0x72, 0xe6, 0x9d, 0x21, 0xf5,
0x2a, 0x82, 0x30, 0x01, 0x01, 0xc1, 0x2a, 0xc3, 0xf8, 0x9b, 0x0a, 0x46, 0xa5, 0x58, 0xe4, 0xad,
0x68, 0xf3, 0x5a, 0x2d, 0xb8, 0xb1, 0xc2, 0xb0, 0x7c, 0x0b, 0x1c, 0xee, 0x64, 0xd1, 0x32, 0x34,
0xe9, 0xd2, 0x4a, 0xbb, 0x4b, 0x4c, 0xdb, 0xb3, 0xa3, 0xf1, 0x5d, 0xa1, 0x8d, 0x23, 0x1c, 0x5d,
0xd8, 0x4d, 0xc3, 0xb3, 0x58, 0xad, 0xc4, 0x1c, 0x3e, 0x37, 0x9a, 0x64, 0x25, 0x54, 0xc7, 0x31,
0x12, 0x3d, 0x80, 0x69, 0x8b, 0x44, 0xe1, 0x00, 0x31, 0xa9, 0xbf, 0x30, 0x9a, 0x68, 0x35, 0x06,
0x60, 0x19, 0x4d, 0xeb, 0x14, 0x1e, 0x01, 0xfd, 0xc2, 0xcd, 0x06, 0xa3, 0x8a, 0x2f, 0xf6, 0xc5,
0x48, 0xfd, 0x0c, 0xcc, 0x28, 0xe3, 0xf6, 0x99, 0xee, 0x3a, 0xe4, 0xb1, 0xe4, 0x3c, 0x8b, 0xd1,
0x11, 0xe5, 0x1d, 0x75, 0xdb, 0x91, 0x7b, 0x22, 0x11, 0xc0, 0x87, 0xd0, 0x0c, 0x07, 0x06, 0xdd,
0x55, 0xeb, 0xf0, 0x56, 0x71, 0x1d, 0xa2, 0x31, 0x15, 0x6c, 0x1b, 0xd0, 0x8a, 0x46, 0x08, 0x2d,
0xa9, 0x74, 0x6f, 0x17, 0xd3, 0xc5, 0xa3, 0x2b, 0xf8, 0x30, 0x4c, 0x4b, 0x03, 0x85, 0x56, 0x54,
0xc6, 0x77, 0x8a, 0x19, 0xe5, 0x61, 0x8e, 0x77, 0x3d, 0xd1, 0x88, 0xc9, 0xa3, 0x52, 0x89, 0x47,
0xe5, 0x0f, 0x1b, 0xd0, 0x8c, 0x2e, 0xea, 0x64, 0x9c, 0x31, 0x87, 0x5e, 0xbf, 0xf0, 0x8c, 0x19,
0xe2, 0x3b, 0x4f, 0xbd, 0x3e, 0xa6, 0x08, 0x3a, 0xc4, 0x81, 0x1d, 0x44, 0x53, 0xf5, 0x5c, 0x31,
0xf4, 0x09, 0x55, 0xc7, 0x1c, 0x85, 0x1e, 0xab, 0x56, 0x5e, 0x1d, 0xf1, 0x21, 0x57, 0x21, 0xc9,
0xb5, 0xf4, 0x2e, 0xb4, 0x6c, 0xba, 0xf5, 0x5b, 0x8f, 0x57, 0xde, 0xb7, 0x8b, 0xe9, 0xba, 0x21,
0x04, 0xc7, 0x68, 0x5a, 0xb7, 0x1d, 0x63, 0x9f, 0xce, 0x6b, 0x46, 0x56, 0x1f, 0xb7, 0x6e, 0xf7,
0x62, 0x10, 0x96, 0x19, 0xd0, 0x4d, 0xb1, 0x77, 0x69, 0x14, 0x78, 0x96, 0xb8, 0xab, 0xe2, 0xfd,
0xcb, 0x87, 0xa9, 0x95, 0x96, 0x4f, 0xe3, 0x4b, 0x63, 0xb0, 0x8c, 0x5c, 0x6d, 0xe9, 0x08, 0xf2,
0x9d, 0x51, 0x6b, 0xdc, 0x11, 0x94, 0x77, 0x47, 0xfa, 0x09, 0xa8, 0x3c, 0xf5, 0xfa, 0xf9, 0x6b,
0x35, 0x1b, 0xee, 0x9c, 0xec, 0x53, 0xea, 0x4c, 0xc8, 0xdf, 0xd0, 0x47, 0x63, 0x92, 0xcb, 0x23,
0x75, 0x7a, 0x8e, 0xd2, 0xfb, 0x62, 0x41, 0xbf, 0xa6, 0xce, 0xb7, 0x37, 0x12, 0xf3, 0x8d, 0xce,
0xb0, 0x4d, 0x8f, 0xf0, 0xbb, 0x0a, 0xd2, 0x4a, 0x3e, 0xee, 0x3a, 0x79, 0x3f, 0xdc, 0x7f, 0x4c,
0xe4, 0x29, 0x92, 0x7d, 0xcb, 0xb9, 0x7e, 0xb1, 0x04, 0xcd, 0xe8, 0x1e, 0x56, 0x3a, 0x08, 0xdf,
0xb4, 0xfd, 0x75, 0x62, 0x58, 0xc4, 0x13, 0xf3, 0xf6, 0xad, 0xc2, 0x0b, 0x5e, 0x9d, 0xae, 0x40,
0xe0, 0x08, 0xab, 0x9f, 0x84, 0x66, 0x28, 0xcd, 0x39, 0x94, 0xfd, 0xb8, 0x0c, 0x75, 0x71, 0x83,
0x2b, 0x59, 0x89, 0xdb, 0x50, 0xef, 0x1b, 0x07, 0xee, 0x30, 0x3c, 0x32, 0x9d, 0x2d, 0xb8, 0x14,
0xd6, 0x79, 0xc8, 0xb4, 0xb1, 0x40, 0xa1, 0xf7, 0xa0, 0xd6, 0xb7, 0xf7, 0xec, 0x40, 0xb8, 0x8f,
0x33, 0x85, 0x70, 0xf6, 0xad, 0x97, 0x63, 0x68, 0xe1, 0xec, 0xe2, 0x46, 0x78, 0xed, 0xb6, 0xb0,
0xf0, 0x67, 0x4c, 0x1b, 0x0b, 0x94, 0x7e, 0x1f, 0xea, 0xbc, 0x3a, 0x93, 0x2d, 0x12, 0x6a, 0x4b,
0x62, 0x4b, 0x67, 0x75, 0xcb, 0xd9, 0x95, 0xce, 0x43, 0x9d, 0x17, 0x9e, 0x63, 0x35, 0x3f, 0x7a,
0x8d, 0x9d, 0x77, 0xfa, 0xfa, 0xc3, 0xf8, 0x1b, 0xdf, 0xa7, 0xff, 0x64, 0xa1, 0x3f, 0x81, 0xc3,
0xab, 0x46, 0x60, 0x6c, 0x1b, 0x3e, 0xc1, 0xc4, 0x74, 0x3d, 0x2b, 0x93, 0xd5, 0xe3, 0x59, 0x22,
0x10, 0x9d, 0xcf, 0x2a, 0xf4, 0x3e, 0x0f, 0x1d, 0xfe, 0xcf, 0x09, 0x1d, 0xfe, 0x51, 0x35, 0x27,
0x9e, 0x37, 0x4e, 0x24, 0x83, 0x1a, 0x5c, 0x2a, 0xa0, 0x77, 0x53, 0xdd, 0x7b, 0x9f, 0x2e, 0x40,
0x2a, 0x9b, 0xef, 0x9b, 0x6a, 0x44, 0xaf, 0x08, 0xab, 0x84, 0xf4, 0xee, 0x26, 0x43, 0x7a, 0x67,
0x0b, 0xd0, 0xa9, 0x98, 0xde, 0x4d, 0x35, 0xa6, 0x57, 0x54, 0xba, 0x1c, 0xd4, 0xfb, 0x3f, 0x16,
0x46, 0xfb, 0xf5, 0x9c, 0xb0, 0xcf, 0x17, 0xd5, 0xb0, 0xcf, 0x08, 0xab, 0xf9, 0x69, 0xc5, 0x7d,
0x7e, 0xa3, 0x9e, 0x13, 0xf7, 0x59, 0x54, 0xe2, 0x3e, 0x23, 0x6a, 0x96, 0x0c, 0xfc, 0xdc, 0x54,
0x03, 0x3f, 0xa7, 0x0b, 0x90, 0x4a, 0xe4, 0x67, 0x51, 0x89, 0xfc, 0x14, 0x15, 0x2a, 0x85, 0x7e,
0x16, 0x95, 0xd0, 0x4f, 0x11, 0x50, 0x8a, 0xfd, 0x2c, 0x2a, 0xb1, 0x9f, 0x22, 0xa0, 0x14, 0xfc,
0x59, 0x54, 0x82, 0x3f, 0x45, 0x40, 0x29, 0xfa, 0x73, 0x53, 0x8d, 0xfe, 0x14, 0xf7, 0x8f, 0x34,
0xe8, 0x9f, 0x07, 0x6a, 0xfe, 0x0b, 0x03, 0x35, 0xbf, 0x52, 0xc9, 0x09, 0xc0, 0xe0, 0xec, 0x00,
0xcc, 0x85, 0xfc, 0x91, 0x2c, 0x8e, 0xc0, 0x8c, 0xbf, 0x0a, 0xa4, 0x43, 0x30, 0xef, 0x27, 0x42,
0x30, 0x67, 0x0a, 0xc0, 0x6a, 0x0c, 0xe6, 0x7f, 0x4d, 0x90, 0xe1, 0xf7, 0xeb, 0x23, 0xce, 0xd3,
0x37, 0xe4, 0xf3, 0xf4, 0x88, 0x95, 0x2c, 0x7d, 0xa0, 0xbe, 0xad, 0x1e, 0xa8, 0xcf, 0x8f, 0x81,
0x55, 0x4e, 0xd4, 0x9b, 0x59, 0x27, 0xea, 0xce, 0x18, 0x2c, 0xb9, 0x47, 0xea, 0xfb, 0xe9, 0x23,
0xf5, 0x85, 0x31, 0xf8, 0x32, 0xcf, 0xd4, 0x9b, 0x59, 0x67, 0xea, 0x71, 0x6a, 0x97, 0x7b, 0xa8,
0x7e, 0x4f, 0x39, 0x54, 0x9f, 0x1b, 0xa7, 0xbb, 0xe2, 0xc5, 0xe1, 0xcb, 0x39, 0xa7, 0xea, 0x77,
0xc7, 0xa1, 0x19, 0x1d, 0xc4, 0xfe, 0xfc, 0x5c, 0xac, 0x16, 0xf3, 0x7b, 0x6f, 0x40, 0x33, 0xbc,
0x4f, 0xa3, 0x7f, 0x13, 0x1a, 0xe1, 0xb3, 0x9d, 0xe4, 0xcc, 0x39, 0x1e, 0x1d, 0xea, 0xf8, 0xee,
0x59, 0xa4, 0xd0, 0x6d, 0xa8, 0xd2, 0xff, 0xc4, 0xb4, 0x78, 0x6b, 0xbc, 0x7b, 0x3b, 0xb4, 0x10,
0xcc, 0x70, 0xfa, 0xbf, 0x1e, 0x03, 0x90, 0x5e, 0x33, 0x8c, 0x5b, 0xec, 0x07, 0xd4, 0x99, 0xf5,
0x03, 0xe2, 0xb1, 0xfb, 0x5a, 0x85, 0xb7, 0xfd, 0xe3, 0x12, 0xa8, 0xb5, 0x04, 0xc4, 0xc3, 0x02,
0x8e, 0x1e, 0x41, 0x33, 0x0c, 0xa4, 0x6a, 0x55, 0x46, 0xf5, 0xee, 0xd8, 0x54, 0x61, 0x68, 0x0f,
0x47, 0x14, 0x68, 0x09, 0xaa, 0xbe, 0xeb, 0x05, 0x5a, 0x8d, 0x51, 0xbd, 0x33, 0x36, 0xd5, 0x96,
0xeb, 0x05, 0x98, 0x41, 0x79, 0xd3, 0xa4, 0xc7, 0xa2, 0x93, 0x34, 0x4d, 0xf1, 0xd8, 0xff, 0x52,
0x89, 0x7c, 0xe8, 0x8a, 0x98, 0x8d, 0xdc, 0x86, 0x2e, 0x8e, 0x3f, 0x4a, 0xf2, 0xac, 0x44, 0x62,
0x13, 0xc4, 0x47, 0x82, 0xef, 0x6f, 0xde, 0x82, 0xb6, 0xe9, 0xee, 0x13, 0x0f, 0xc7, 0x37, 0x99,
0xc4, 0x65, 0xb3, 0x94, 0x1c, 0xe9, 0xd0, 0xdc, 0xb5, 0x2d, 0xd2, 0x35, 0x85, 0xff, 0x6b, 0xe2,
0x28, 0x8d, 0x1e, 0x40, 0x93, 0xc5, 0xd8, 0xc3, 0x08, 0xff, 0x64, 0x95, 0xe4, 0xa1, 0xfe, 0x90,
0x80, 0x16, 0xc4, 0x0a, 0xbf, 0x67, 0x07, 0xac, 0x0f, 0x9b, 0x38, 0x4a, 0xd3, 0x0a, 0xb3, 0xeb,
0x62, 0x72, 0x85, 0x1b, 0xbc, 0xc2, 0x49, 0x39, 0xba, 0x0a, 0xaf, 0x30, 0x59, 0xe2, 0x88, 0xc9,
0x43, 0xf5, 0x4d, 0x9c, 0x9d, 0xc9, 0xae, 0xc7, 0x19, 0x3d, 0x7e, 0x35, 0x9c, 0x05, 0xef, 0x6a,
0x38, 0x16, 0xa0, 0x0b, 0x70, 0xc4, 0x22, 0x3b, 0xc6, 0xb0, 0x1f, 0x3c, 0x21, 0x7b, 0x83, 0xbe,
0x11, 0x90, 0xae, 0xc5, 0xde, 0xab, 0xb6, 0x70, 0x3a, 0x03, 0x5d, 0x82, 0xa3, 0x42, 0xc8, 0xa7,
0x31, 0x1d, 0x8d, 0xae, 0xc5, 0x9e, 0x6f, 0xb6, 0x70, 0x56, 0x96, 0xfe, 0xa3, 0x2a, 0x1d, 0x74,
0x66, 0xda, 0x1f, 0x40, 0xc5, 0xb0, 0x2c, 0xb1, 0x6c, 0x5e, 0x99, 0x70, 0x82, 0x88, 0x27, 0xd9,
0x94, 0x01, 0x6d, 0x46, 0x37, 0xeb, 0xf8, 0xc2, 0x79, 0x7d, 0x52, 0xae, 0xe8, 0x19, 0xbd, 0xe0,
0xa1, 0x8c, 0x43, 0x7e, 0xb7, 0xbb, 0xf2, 0x93, 0x31, 0x46, 0x57, 0xbe, 0x05, 0x0f, 0xba, 0x0f,
0x55, 0x56, 0x43, 0xbe, 0xb0, 0x5e, 0x9d, 0x94, 0xef, 0x11, 0xaf, 0x1f, 0xe3, 0xd0, 0x4d, 0x7e,
0xf7, 0x4d, 0xba, 0x57, 0x59, 0x52, 0xef, 0x55, 0x2e, 0x43, 0xcd, 0x0e, 0xc8, 0x5e, 0xfa, 0x9a,
0xed, 0x48, 0x53, 0x15, 0x9e, 0x87, 0x43, 0x47, 0x5e, 0xf7, 0xfb, 0x28, 0xba, 0x72, 0x9d, 0xf4,
0x87, 0x77, 0xa1, 0x4a, 0xe1, 0xa9, 0xbd, 0xe4, 0x38, 0x05, 0x33, 0xa4, 0x7e, 0x19, 0xaa, 0xb4,
0xb1, 0x23, 0x5a, 0x27, 0xea, 0x53, 0x8e, 0xea, 0xb3, 0x3c, 0x0d, 0x2d, 0x77, 0x40, 0x3c, 0x36,
0x31, 0xf4, 0x7f, 0xac, 0x4a, 0x97, 0xe2, 0xba, 0xb2, 0x8d, 0x5d, 0x9b, 0xd8, 0x73, 0xca, 0x56,
0x86, 0x13, 0x56, 0x76, 0x63, 0x72, 0xb6, 0x94, 0x9d, 0xe1, 0x84, 0x9d, 0xfd, 0x04, 0x9c, 0x29,
0x4b, 0x7b, 0xa8, 0x58, 0xda, 0xf5, 0xc9, 0x19, 0x15, 0x5b, 0x23, 0x45, 0xb6, 0xb6, 0xaa, 0xda,
0x5a, 0x67, 0xbc, 0x21, 0x8f, 0x96, 0xa6, 0x31, 0xac, 0xed, 0xab, 0xb9, 0xd6, 0xb6, 0xac, 0x58,
0xdb, 0xa4, 0x45, 0x7f, 0x46, 0xf6, 0xf6, 0x37, 0x55, 0xa8, 0xd2, 0xe5, 0x11, 0xad, 0xc9, 0xb6,
0xf6, 0xee, 0x44, 0x4b, 0xab, 0x6c, 0x67, 0x1b, 0x09, 0x3b, 0xbb, 0x3a, 0x19, 0x53, 0xca, 0xc6,
0x36, 0x12, 0x36, 0x36, 0x21, 0x5f, 0xca, 0xbe, 0xd6, 0x15, 0xfb, 0xba, 0x3c, 0x19, 0x9b, 0x62,
0x5b, 0x46, 0x91, 0x6d, 0xdd, 0x55, 0x6d, 0x6b, 0xcc, 0xdd, 0x1b, 0xdb, 0xab, 0x8c, 0x61, 0x57,
0x1f, 0xe6, 0xda, 0xd5, 0x6d, 0xc5, 0xae, 0x26, 0x29, 0xf6, 0x33, 0xb2, 0xa9, 0xab, 0x7c, 0xd3,
0x29, 0xee, 0x19, 0x8f, 0xb9, 0xe9, 0xd4, 0xaf, 0x41, 0x2b, 0x7e, 0x0e, 0x9e, 0x71, 0x0b, 0x9f,
0xab, 0x85, 0xa5, 0x86, 0x49, 0xfd, 0x0a, 0xb4, 0xe2, 0x27, 0xde, 0x19, 0x65, 0xf9, 0x2c, 0x53,
0xa0, 0x44, 0x4a, 0x5f, 0x83, 0x23, 0xe9, 0x07, 0xa8, 0x19, 0x71, 0x78, 0xe9, 0x0a, 0x79, 0xf8,
0xe2, 0x44, 0x12, 0xe9, 0x2f, 0x60, 0x36, 0xf1, 0xa4, 0x74, 0x62, 0x0e, 0x74, 0x45, 0xda, 0x22,
0x57, 0xc4, 0x19, 0x3c, 0xfb, 0x52, 0x7c, 0xbc, 0x11, 0xd6, 0x57, 0x61, 0xb6, 0xa0, 0xf2, 0xe3,
0xdc, 0x89, 0xff, 0x3a, 0x4c, 0x8f, 0xaa, 0xfb, 0x67, 0x70, 0x67, 0x3f, 0x80, 0x76, 0xea, 0x39,
0x7c, 0xb2, 0x98, 0x4d, 0x80, 0x5e, 0xa4, 0x23, 0x8c, 0xf6, 0xd2, 0x04, 0x2f, 0x14, 0x18, 0x0e,
0x4b, 0x1c, 0xfa, 0xef, 0x94, 0xe0, 0x48, 0xfa, 0x2d, 0xfc, 0xb8, 0x87, 0x1f, 0x0d, 0x1a, 0x8c,
0x2b, 0x7a, 0xd8, 0x11, 0x26, 0xd1, 0x23, 0x38, 0xe4, 0xf7, 0x6d, 0x93, 0xac, 0xec, 0x1a, 0x4e,
0x8f, 0xf8, 0xe2, 0x44, 0x53, 0xf0, 0x9e, 0x7d, 0x2b, 0x46, 0x60, 0x05, 0xae, 0xbf, 0x80, 0x69,
0x29, 0x13, 0xdd, 0x82, 0xb2, 0x3b, 0x48, 0xdd, 0x6b, 0xcc, 0xe7, 0x7c, 0x1c, 0xce, 0x37, 0x5c,
0x76, 0x07, 0xe9, 0x29, 0x29, 0x4f, 0xdf, 0x8a, 0x32, 0x7d, 0xf5, 0x07, 0x70, 0x24, 0xfd, 0xdc,
0x3c, 0xd9, 0x3d, 0x67, 0x53, 0x51, 0x02, 0xde, 0x4d, 0xc9, 0x23, 0xff, 0x22, 0x1c, 0x4e, 0x3e,
0x22, 0xcf, 0x78, 0x74, 0x13, 0xbf, 0x5d, 0x0a, 0xc3, 0xf5, 0x0b, 0xbf, 0x5c, 0x82, 0x59, 0xb5,
0x21, 0xe8, 0x38, 0x20, 0x55, 0xb2, 0xe1, 0x3a, 0xa4, 0x3d, 0x85, 0x5e, 0x81, 0x23, 0xaa, 0x7c,
0xc9, 0xb2, 0xda, 0xa5, 0xb4, 0x3a, 0x75, 0x5b, 0xed, 0x32, 0xd2, 0xe0, 0x58, 0xa2, 0x87, 0x98,
0x13, 0x6d, 0x57, 0xd0, 0x6b, 0xf0, 0x4a, 0x32, 0x67, 0xd0, 0x37, 0x4c, 0xd2, 0xae, 0xea, 0xff,
0x5c, 0x86, 0xea, 0x53, 0x9f, 0x78, 0xfa, 0x3f, 0x94, 0xc3, 0x57, 0x1a, 0x37, 0xa0, 0xca, 0xde,
0x77, 0x4b, 0x8f, 0x16, 0x4b, 0x89, 0x47, 0x8b, 0xca, 0xc3, 0xb7, 0xf8, 0xd1, 0xe2, 0x0d, 0xa8,
0xb2, 0x17, 0xdd, 0x93, 0x23, 0x7f, 0xa1, 0x04, 0xad, 0xf8, 0x75, 0xf5, 0xc4, 0x78, 0xf9, 0x55,
0x48, 0x59, 0x7d, 0x15, 0xf2, 0x16, 0xd4, 0x3c, 0xf6, 0x7e, 0x83, 0x7b, 0x99, 0xe4, 0x5b, 0x13,
0x56, 0x20, 0xe6, 0x2a, 0x3a, 0x81, 0x69, 0xf9, 0xed, 0xf8, 0xe4, 0xd5, 0x38, 0x2d, 0x7e, 0x38,
0xa6, 0x6b, 0xf9, 0x4b, 0x9e, 0x67, 0x1c, 0x08, 0xc3, 0x54, 0x85, 0xfa, 0x1c, 0x54, 0x37, 0x6d,
0xa7, 0x97, 0xfd, 0x56, 0x54, 0xff, 0x41, 0x09, 0x1a, 0xe2, 0xf2, 0xae, 0xbe, 0x08, 0x95, 0x0d,
0xf2, 0x82, 0x56, 0x44, 0x5c, 0x1b, 0x4e, 0x55, 0xe4, 0x11, 0x6b, 0x85, 0xd0, 0xc7, 0xa1, 0x9a,
0x7e, 0x33, 0x5a, 0x26, 0x27, 0xc7, 0xde, 0x80, 0x2a, 0x7b, 0xf2, 0x3d, 0x39, 0xf2, 0xb7, 0x9a,
0x50, 0xe7, 0x0f, 0x2e, 0xf5, 0xef, 0x35, 0xa1, 0xce, 0x9f, 0x81, 0xa3, 0xdb, 0xd0, 0xf0, 0x87,
0x7b, 0x7b, 0x86, 0x77, 0xa0, 0x65, 0xff, 0x64, 0xa0, 0xf2, 0x6a, 0xbc, 0xb3, 0xc5, 0x75, 0x71,
0x08, 0x42, 0xd7, 0xa0, 0x6a, 0x1a, 0x3b, 0x24, 0xf5, 0x39, 0x37, 0x0b, 0xbc, 0x62, 0xec, 0x10,
0xcc, 0xd4, 0xd1, 0x5d, 0x68, 0x8a, 0x61, 0xf1, 0x45, 0x3c, 0x67, 0x74, 0xb9, 0xe1, 0x60, 0x46,
0x28, 0xfd, 0x3e, 0x34, 0x44, 0x65, 0xd0, 0x9d, 0xe8, 0xb9, 0x69, 0x32, 0xf2, 0x9c, 0xd9, 0x84,
0x03, 0xc7, 0x4c, 0x3c, 0x3c, 0xfd, 0xb3, 0x32, 0x54, 0x69, 0xe5, 0x3e, 0x35, 0x13, 0x9a, 0x07,
0xe8, 0x1b, 0x7e, 0xb0, 0x39, 0xec, 0xf7, 0x89, 0x25, 0x1e, 0xd2, 0x49, 0x12, 0x74, 0x1e, 0x0e,
0xf3, 0x94, 0xbf, 0xbb, 0x35, 0x34, 0x4d, 0x12, 0xbd, 0x06, 0x4d, 0x8a, 0xd1, 0x12, 0xd4, 0xd8,
0x0f, 0x93, 0x89, 0x5d, 0xe1, 0xdb, 0x85, 0x3d, 0xdb, 0xd9, 0xb4, 0x1d, 0x51, 0x1b, 0x8e, 0xd4,
0x5d, 0x68, 0x45, 0x32, 0x3a, 0x09, 0x07, 0xb6, 0xe3, 0xd8, 0x4e, 0x4f, 0x58, 0x74, 0x98, 0xa4,
0x8b, 0x0e, 0xfd, 0x57, 0xd4, 0xb7, 0x86, 0x45, 0x8a, 0xca, 0x77, 0x0c, 0xbb, 0x2f, 0xaa, 0x58,
0xc3, 0x22, 0x45, 0x99, 0x86, 0xe2, 0xf1, 0x7c, 0x95, 0x35, 0x30, 0x4c, 0xea, 0x1f, 0x97, 0xa2,
0x37, 0xd7, 0x59, 0x6f, 0x30, 0x53, 0xb1, 0xa4, 0x39, 0x39, 0xa0, 0xcd, 0x17, 0x04, 0x29, 0x44,
0x7d, 0x1c, 0xea, 0xae, 0xd3, 0xb7, 0x1d, 0x22, 0x62, 0x47, 0x22, 0x95, 0xe8, 0xe3, 0x5a, 0xaa,
0x8f, 0x45, 0xfe, 0x9a, 0x65, 0xd3, 0x2a, 0xd6, 0xe3, 0x7c, 0x2e, 0x41, 0xef, 0x43, 0xc3, 0x22,
0xfb, 0xb6, 0x49, 0x7c, 0xad, 0xc1, 0x4c, 0xef, 0xd4, 0xc8, 0xbe, 0x5d, 0x65, 0xba, 0x38, 0xc4,
0xe8, 0x01, 0xd4, 0xb9, 0x28, 0x6a, 0x52, 0x49, 0x6a, 0x52, 0x5c, 0xe9, 0xf2, 0x88, 0x4a, 0x57,
0x0a, 0x2a, 0x5d, 0x4d, 0x56, 0x7a, 0xc1, 0x02, 0x88, 0xcd, 0x0d, 0x4d, 0x43, 0xe3, 0xa9, 0xf3,
0xdc, 0x71, 0x5f, 0x38, 0xed, 0x29, 0x9a, 0x78, 0xbc, 0xb3, 0x43, 0x4b, 0x69, 0x97, 0x68, 0x82,
0xea, 0xd9, 0x4e, 0xaf, 0x5d, 0x46, 0x00, 0x75, 0x9a, 0x20, 0x56, 0xbb, 0x42, 0xff, 0xbf, 0xc7,
0xc6, 0xaf, 0x5d, 0x45, 0xaf, 0xc2, 0xd1, 0xae, 0x63, 0xba, 0x7b, 0x03, 0x23, 0xb0, 0xb7, 0xfb,
0xe4, 0x19, 0xf1, 0x7c, 0xdb, 0x75, 0xda, 0x35, 0xfd, 0xdf, 0x4b, 0xfc, 0xab, 0xaf, 0x7e, 0x17,
0x0e, 0x29, 0xbf, 0xe6, 0xa0, 0x41, 0xc3, 0x1f, 0xf0, 0x1f, 0x6f, 0x15, 0xfb, 0x6e, 0x91, 0x64,
0x56, 0xc2, 0x5f, 0xbf, 0x8b, 0x2d, 0x0b, 0x4f, 0xe9, 0xf7, 0x00, 0xa4, 0xdf, 0x70, 0x98, 0x07,
0xd8, 0x3e, 0x08, 0x88, 0xcf, 0x7f, 0xbf, 0x81, 0x52, 0x54, 0xb1, 0x24, 0x91, 0xf9, 0xcb, 0x0a,
0xbf, 0x7e, 0x1d, 0x40, 0xfa, 0x05, 0x07, 0x3a, 0x7f, 0x68, 0x6a, 0x39, 0x49, 0x96, 0x14, 0xeb,
0x1d, 0xd1, 0x82, 0xf0, 0xb7, 0x1a, 0xc2, 0x1a, 0xf0, 0x28, 0x9d, 0x5c, 0x03, 0x26, 0xd1, 0xd7,
0x00, 0xe2, 0x9f, 0x2b, 0xd0, 0x17, 0x23, 0x17, 0xfd, 0x0e, 0x54, 0x2d, 0x23, 0x30, 0x84, 0x77,
0x7c, 0x2d, 0xb1, 0x42, 0xc5, 0x10, 0xcc, 0xd4, 0xf4, 0xdf, 0x2e, 0xc1, 0x21, 0xf9, 0xa7, 0x19,
0xf4, 0x0f, 0xa0, 0xca, 0x7e, 0xdb, 0xe1, 0x0e, 0x1c, 0x92, 0x7f, 0x9b, 0x21, 0xf5, 0xcb, 0xb6,
0x9c, 0x4f, 0x86, 0x62, 0x05, 0xa0, 0x77, 0xa3, 0x2a, 0x7d, 0x6a, 0xaa, 0x4b, 0xd0, 0x10, 0x3f,
0xf5, 0xa0, 0x9f, 0x81, 0x56, 0xfc, 0xcb, 0x0e, 0xd4, 0x47, 0x70, 0x79, 0x38, 0xca, 0x22, 0xa9,
0x7f, 0xb7, 0x04, 0xad, 0xe8, 0xe7, 0x17, 0xf4, 0xa5, 0xa8, 0x2a, 0x8b, 0x09, 0x87, 0x99, 0xff,
0x93, 0x0d, 0xaa, 0xa3, 0x5c, 0x58, 0x0c, 0x17, 0x23, 0x74, 0x88, 0x3d, 0x74, 0xf6, 0xa9, 0x21,
0xb6, 0xa7, 0xd0, 0x0c, 0xb4, 0x56, 0x5c, 0xc7, 0x21, 0x66, 0x40, 0xe8, 0x76, 0xaa, 0xcd, 0x7a,
0x33, 0x96, 0x94, 0x17, 0xbe, 0x0d, 0x33, 0x98, 0xf8, 0x03, 0xd7, 0xf1, 0xc9, 0x4f, 0xeb, 0xf7,
0x8d, 0x73, 0x7f, 0xa9, 0x78, 0xe1, 0x07, 0x15, 0xa8, 0xb1, 0xe5, 0x55, 0xff, 0x83, 0x4a, 0xb4,
0x11, 0xc8, 0xb8, 0x7c, 0x15, 0x5f, 0x91, 0x98, 0x95, 0xc6, 0x45, 0x59, 0x98, 0xe5, 0x38, 0xfb,
0x65, 0xf9, 0x6a, 0xc4, 0xac, 0xf4, 0xc3, 0x2d, 0x2a, 0x42, 0xb9, 0x12, 0xf1, 0x1e, 0x34, 0x07,
0x9e, 0xdb, 0xf3, 0xe8, 0x0e, 0xa0, 0x9a, 0xf8, 0xb9, 0x0c, 0x15, 0xb6, 0x29, 0xd4, 0x70, 0x04,
0xd0, 0x37, 0xa0, 0x19, 0x4a, 0x73, 0x1e, 0x84, 0x23, 0xa8, 0x5a, 0xae, 0xf0, 0x62, 0x15, 0xcc,
0xfe, 0xa7, 0xfd, 0x22, 0x7a, 0x30, 0xdc, 0xbd, 0x8b, 0xe4, 0xc2, 0xd7, 0xc4, 0xa7, 0xab, 0x19,
0x68, 0xad, 0x7a, 0xee, 0x80, 0x3d, 0x09, 0x6e, 0x4f, 0x51, 0x9f, 0xd3, 0xdd, 0x1b, 0xb8, 0x5e,
0xd0, 0x2e, 0xd1, 0xff, 0xd7, 0x5e, 0xb2, 0xff, 0xcb, 0x74, 0xc8, 0xb7, 0x8c, 0x7d, 0x42, 0xd5,
0xda, 0x15, 0x84, 0xe8, 0xc1, 0x91, 0x85, 0xeb, 0xc5, 0xda, 0xd1, 0xae, 0x52, 0xa2, 0x47, 0x76,
0x8f, 0xef, 0x87, 0xdb, 0xb5, 0x85, 0xa5, 0xf0, 0x8a, 0x42, 0x13, 0xaa, 0x62, 0xff, 0x3d, 0x0d,
0x0d, 0x3c, 0x64, 0x0b, 0x58, 0xbb, 0x44, 0xc5, 0x74, 0x57, 0xc4, 0xa9, 0x57, 0x0c, 0xc7, 0x24,
0x7d, 0xe6, 0xf4, 0x5a, 0x50, 0x5b, 0xf3, 0x3c, 0xd7, 0x6b, 0x57, 0x97, 0xe7, 0xfe, 0xfc, 0xe3,
0xf9, 0xd2, 0x0f, 0x3f, 0x9e, 0x2f, 0xfd, 0xf8, 0xe3, 0xf9, 0xd2, 0xaf, 0x7d, 0x32, 0x3f, 0xf5,
0xc3, 0x4f, 0xe6, 0xa7, 0xfe, 0xfe, 0x93, 0xf9, 0xa9, 0x8f, 0xca, 0x83, 0xed, 0xed, 0x3a, 0xfb,
0xb6, 0x7c, 0xe5, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x83, 0x93, 0x5a, 0xa2, 0x9d, 0x5b, 0x00,
0x00,
// 5576 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5c, 0x4b, 0x6c, 0x1c, 0xc9,
0x79, 0xe6, 0xbc, 0x67, 0x7e, 0x8a, 0xd4, 0xa8, 0xa4, 0xd5, 0xf6, 0xb6, 0xb8, 0x5c, 0x2d, 0xf5,
0xf4, 0xae, 0x76, 0xa4, 0xd5, 0x8b, 0xb2, 0xac, 0x95, 0xc4, 0x97, 0x96, 0xa3, 0x07, 0xc5, 0x14,
0x25, 0x79, 0xbd, 0x6b, 0x18, 0x6e, 0x76, 0x17, 0x87, 0x6d, 0x0d, 0xbb, 0xc7, 0xdd, 0x3d, 0x94,
0x68, 0x27, 0x4e, 0x90, 0x07, 0x72, 0x49, 0x90, 0x9c, 0x9c, 0x20, 0xb7, 0x04, 0x09, 0x90, 0x43,
0x10, 0xc4, 0xc8, 0xc5, 0xa7, 0x20, 0x40, 0x10, 0x20, 0xaf, 0x83, 0x93, 0x53, 0x6e, 0x36, 0x76,
0x2f, 0xb9, 0x04, 0x48, 0x62, 0x20, 0xc8, 0x29, 0x08, 0xea, 0xd1, 0xdd, 0x55, 0xfd, 0x98, 0x9e,
0xf1, 0xae, 0xf3, 0x40, 0xf6, 0x44, 0xd6, 0x5f, 0xff, 0xf7, 0xd5, 0xeb, 0xaf, 0xbf, 0xaa, 0xfe,
0xae, 0x1a, 0x38, 0x3e, 0xd8, 0xbe, 0x38, 0xf0, 0xdc, 0xc0, 0xf5, 0x2f, 0x92, 0x7d, 0xe2, 0x04,
0x7e, 0x87, 0xa5, 0x50, 0xc3, 0x70, 0x0e, 0x82, 0x83, 0x01, 0xd1, 0x4f, 0x0f, 0x9e, 0xf7, 0x2e,
0xf6, 0xed, 0xed, 0x8b, 0x83, 0xed, 0x8b, 0x7b, 0xae, 0x45, 0xfa, 0xa1, 0x3a, 0x4b, 0x08, 0x75,
0x7d, 0xae, 0xe7, 0xba, 0xbd, 0x3e, 0xe1, 0x79, 0xdb, 0xc3, 0x9d, 0x8b, 0x7e, 0xe0, 0x0d, 0xcd,
0x80, 0xe7, 0x2e, 0xfc, 0xf8, 0x7b, 0x25, 0xa8, 0xad, 0x51, 0x7a, 0x74, 0x19, 0x9a, 0x7b, 0xc4,
0xf7, 0x8d, 0x1e, 0xf1, 0xb5, 0xd2, 0xc9, 0xca, 0xf9, 0xe9, 0xcb, 0xc7, 0x3b, 0xa2, 0xa8, 0x0e,
0xd3, 0xe8, 0x3c, 0xe2, 0xd9, 0x38, 0xd2, 0x43, 0x73, 0xd0, 0x32, 0x5d, 0x27, 0x20, 0x2f, 0x83,
0xae, 0xa5, 0x95, 0x4f, 0x96, 0xce, 0xb7, 0x70, 0x2c, 0x40, 0x57, 0xa1, 0x65, 0x3b, 0x76, 0x60,
0x1b, 0x81, 0xeb, 0x69, 0x95, 0x93, 0x25, 0x85, 0x92, 0x55, 0xb2, 0xb3, 0x64, 0x9a, 0xee, 0xd0,
0x09, 0x70, 0xac, 0x88, 0x34, 0x68, 0x04, 0x9e, 0x61, 0x92, 0xae, 0xa5, 0x55, 0x19, 0x63, 0x98,
0xd4, 0xff, 0xe1, 0x02, 0x34, 0x44, 0x1d, 0xd0, 0x1d, 0x98, 0x36, 0x38, 0x76, 0x6b, 0xd7, 0x7d,
0xa1, 0x95, 0x18, 0xfb, 0x89, 0x44, 0x85, 0x05, 0x7b, 0x87, 0xaa, 0xac, 0x4f, 0x61, 0x19, 0x81,
0xba, 0x30, 0x2b, 0x92, 0xab, 0x24, 0x30, 0xec, 0xbe, 0xaf, 0xfd, 0x35, 0x27, 0x99, 0xcf, 0x21,
0x11, 0x6a, 0xeb, 0x53, 0x38, 0x01, 0x44, 0x5f, 0x81, 0xa3, 0x42, 0xb2, 0xe2, 0x3a, 0x3b, 0x76,
0xef, 0xe9, 0xc0, 0x32, 0x02, 0xa2, 0xfd, 0x0d, 0xe7, 0x3b, 0x9d, 0xc3, 0xc7, 0x75, 0x3b, 0x5c,
0x79, 0x7d, 0x0a, 0x67, 0x71, 0xa0, 0x7b, 0x30, 0x23, 0xc4, 0x82, 0xf4, 0x6f, 0x39, 0xe9, 0xeb,
0x39, 0xa4, 0x11, 0x9b, 0x0a, 0x43, 0x1f, 0xc1, 0x31, 0x21, 0x78, 0x68, 0x3b, 0xcf, 0x57, 0x76,
0x8d, 0x7e, 0x9f, 0x38, 0x3d, 0xa2, 0xfd, 0xdd, 0xe8, 0x3a, 0x2a, 0xca, 0xeb, 0x53, 0x38, 0x93,
0x04, 0x3d, 0x86, 0xb6, 0xbb, 0xfd, 0x0d, 0x62, 0x86, 0x1d, 0xb2, 0x45, 0x02, 0xad, 0xcd, 0x78,
0xdf, 0x4c, 0xf0, 0x3e, 0x66, 0x6a, 0x61, 0x57, 0x76, 0xb6, 0x48, 0xb0, 0x3e, 0x85, 0x53, 0x60,
0xf4, 0x14, 0x90, 0x22, 0x5b, 0xda, 0x23, 0x8e, 0xa5, 0x5d, 0x66, 0x94, 0xa7, 0x46, 0x53, 0x32,
0xd5, 0xf5, 0x29, 0x9c, 0x41, 0x90, 0xa2, 0x7d, 0xea, 0xf8, 0x24, 0xd0, 0xae, 0x8c, 0x43, 0xcb,
0x54, 0x53, 0xb4, 0x4c, 0x4a, 0xfb, 0x96, 0x4b, 0x31, 0xe9, 0x1b, 0x81, 0xed, 0x3a, 0xa2, 0xbe,
0x57, 0x19, 0xf1, 0x99, 0x6c, 0xe2, 0x48, 0x37, 0xaa, 0x71, 0x26, 0x09, 0xfa, 0x1a, 0xbc, 0x92,
0x90, 0x63, 0xb2, 0xe7, 0xee, 0x13, 0xed, 0x1a, 0x63, 0x3f, 0x5b, 0xc4, 0xce, 0xb5, 0xd7, 0xa7,
0x70, 0x36, 0x0d, 0x5a, 0x86, 0x43, 0x61, 0x06, 0xa3, 0xbd, 0xce, 0x68, 0xe7, 0xf2, 0x68, 0x05,
0x99, 0x82, 0x91, 0xeb, 0xe8, 0x07, 0x9e, 0x6d, 0x32, 0x7e, 0x6a, 0x04, 0x8b, 0xa3, 0xeb, 0x18,
0x2b, 0x0b, 0x4b, 0xc8, 0xa6, 0x41, 0x18, 0x0e, 0xfb, 0xc3, 0x6d, 0xdf, 0xf4, 0xec, 0x01, 0x95,
0x2d, 0x59, 0x96, 0x76, 0x6b, 0x14, 0xf3, 0x96, 0xa4, 0xdc, 0x59, 0xb2, 0x68, 0xe7, 0x26, 0x09,
0xd0, 0x47, 0x80, 0x64, 0x91, 0x68, 0xfd, 0x7b, 0x8c, 0xf6, 0x0b, 0x63, 0xd0, 0x46, 0x5d, 0x91,
0x41, 0x83, 0x0c, 0x38, 0x26, 0x4b, 0x37, 0x5d, 0xdf, 0xa6, 0x7f, 0xb5, 0xdb, 0x8c, 0xfe, 0xed,
0x31, 0xe8, 0x43, 0x08, 0xb5, 0x8b, 0x2c, 0xaa, 0x64, 0x11, 0x2b, 0x74, 0x56, 0x12, 0xcf, 0xd7,
0xee, 0x8c, 0x5d, 0x44, 0x08, 0x49, 0x16, 0x11, 0xca, 0x93, 0x5d, 0xf4, 0xbe, 0xe7, 0x0e, 0x07,
0xbe, 0x76, 0x77, 0xec, 0x2e, 0xe2, 0x80, 0x64, 0x17, 0x71, 0x29, 0xba, 0x0e, 0xcd, 0xed, 0xbe,
0x6b, 0x3e, 0xa7, 0x83, 0x59, 0x66, 0x94, 0x5a, 0x82, 0x72, 0x99, 0x66, 0x8b, 0xe1, 0x8b, 0x74,
0xa9, 0xdf, 0x67, 0xff, 0xaf, 0x92, 0x3e, 0x09, 0x88, 0x58, 0x55, 0x4e, 0x64, 0x42, 0xb9, 0x0a,
0xf5, 0xfb, 0x12, 0x02, 0xad, 0xc2, 0xf4, 0x8e, 0xdd, 0x27, 0xfe, 0xd3, 0x41, 0xdf, 0x35, 0xf8,
0x12, 0x33, 0x7d, 0xf9, 0x64, 0x26, 0xc1, 0xbd, 0x58, 0x8f, 0xb2, 0x48, 0x30, 0x74, 0x1b, 0x5a,
0x7b, 0x86, 0xf7, 0xdc, 0xef, 0x3a, 0x3b, 0xae, 0x56, 0xcb, 0x5c, 0x37, 0x38, 0xc7, 0xa3, 0x50,
0x6b, 0x7d, 0x0a, 0xc7, 0x10, 0xba, 0xfa, 0xb0, 0x4a, 0x6d, 0x91, 0xe0, 0x9e, 0x4d, 0xfa, 0x96,
0xaf, 0xd5, 0x19, 0xc9, 0x1b, 0x99, 0x24, 0x5b, 0x24, 0xe8, 0x70, 0x35, 0xba, 0xfa, 0xa8, 0x40,
0xf4, 0x01, 0x1c, 0x0d, 0x25, 0x2b, 0xbb, 0x76, 0xdf, 0xf2, 0x88, 0xd3, 0xb5, 0x7c, 0xad, 0x91,
0xe9, 0xd8, 0x63, 0x3e, 0x49, 0x97, 0x2e, 0x3e, 0x19, 0x14, 0xd4, 0xb1, 0x85, 0x62, 0x79, 0x4a,
0x6a, 0xcd, 0x4c, 0xc7, 0x16, 0x53, 0xcb, 0xca, 0xd4, 0xba, 0xb2, 0x48, 0x90, 0x05, 0xaf, 0x86,
0xf2, 0x65, 0xc3, 0x7c, 0xde, 0xf3, 0xdc, 0xa1, 0x63, 0xad, 0xb8, 0x7d, 0xd7, 0xd3, 0x5a, 0x8c,
0xff, 0x7c, 0x2e, 0x7f, 0x42, 0x7f, 0x7d, 0x0a, 0xe7, 0x51, 0xa1, 0x15, 0x38, 0x14, 0x66, 0x3d,
0x21, 0x2f, 0x03, 0x0d, 0x32, 0x57, 0xcf, 0x98, 0x9a, 0x2a, 0x51, 0xff, 0x26, 0x83, 0x64, 0x12,
0x6a, 0x12, 0xda, 0x74, 0x01, 0x09, 0x55, 0x92, 0x49, 0x68, 0x5a, 0x26, 0xa1, 0xab, 0xa7, 0x36,
0x53, 0x40, 0x42, 0x95, 0x64, 0x12, 0x9a, 0xa6, 0x2b, 0x6d, 0xd4, 0x52, 0xd7, 0x7d, 0x4e, 0xed,
0x49, 0x9b, 0xcd, 0x5c, 0x69, 0xa5, 0xde, 0x12, 0x8a, 0x74, 0xa5, 0x4d, 0x82, 0xe9, 0xfe, 0x22,
0x94, 0x2d, 0xf5, 0xed, 0x9e, 0xa3, 0x1d, 0x1e, 0x61, 0xcb, 0x94, 0x8d, 0x69, 0xd1, 0xfd, 0x85,
0x02, 0x43, 0x77, 0xc5, 0xb4, 0xdc, 0x22, 0xc1, 0xaa, 0xbd, 0xaf, 0x1d, 0xc9, 0x5c, 0x45, 0x62,
0x96, 0x55, 0x7b, 0x3f, 0x9a, 0x97, 0x1c, 0x22, 0x37, 0x2d, 0x5c, 0xa3, 0xb4, 0x57, 0x0a, 0x9a,
0x16, 0x2a, 0xca, 0x4d, 0x0b, 0x65, 0x72, 0xd3, 0x1e, 0x1a, 0x01, 0x79, 0xa9, 0xbd, 0x56, 0xd0,
0x34, 0xa6, 0x25, 0x37, 0x8d, 0x09, 0xe8, 0xea, 0x16, 0x0a, 0x9e, 0x11, 0x2f, 0xb0, 0x4d, 0xa3,
0xcf, 0xbb, 0xea, 0x74, 0xe6, 0x1a, 0x14, 0xf3, 0x29, 0xda, 0x74, 0x75, 0xcb, 0xa4, 0x91, 0x1b,
0xfe, 0xc4, 0xd8, 0xee, 0x13, 0xec, 0xbe, 0xd0, 0xce, 0x14, 0x34, 0x3c, 0x54, 0x94, 0x1b, 0x1e,
0xca, 0x64, 0xdf, 0xf2, 0x65, 0xdb, 0xea, 0x91, 0x40, 0x3b, 0x5f, 0xe0, 0x5b, 0xb8, 0x9a, 0xec,
0x5b, 0xb8, 0x24, 0xf2, 0x00, 0xab, 0x46, 0x60, 0xec, 0xdb, 0xe4, 0xc5, 0x33, 0x9b, 0xbc, 0xa0,
0x0b, 0xfb, 0xd1, 0x11, 0x1e, 0x20, 0xd4, 0xed, 0x08, 0xe5, 0xc8, 0x03, 0x24, 0x48, 0x22, 0x0f,
0x20, 0xcb, 0x85, 0x5b, 0x3f, 0x36, 0xc2, 0x03, 0x28, 0xfc, 0x91, 0x8f, 0xcf, 0xa3, 0x42, 0x06,
0x1c, 0x4f, 0x65, 0x3d, 0xf6, 0x2c, 0xe2, 0x69, 0xaf, 0xb3, 0x42, 0xce, 0x15, 0x17, 0xc2, 0xd4,
0xd7, 0xa7, 0x70, 0x0e, 0x51, 0xaa, 0x88, 0x2d, 0x77, 0xe8, 0x99, 0x84, 0xf6, 0xd3, 0xa9, 0x71,
0x8a, 0x88, 0xd4, 0x53, 0x45, 0x44, 0x39, 0x68, 0x1f, 0x5e, 0x8f, 0x72, 0x68, 0xc1, 0x6c, 0x15,
0x65, 0xa5, 0x8b, 0x73, 0xc1, 0x59, 0x56, 0x52, 0x67, 0x74, 0x49, 0x49, 0xd4, 0xfa, 0x14, 0x1e,
0x4d, 0x8b, 0x0e, 0x60, 0x5e, 0x51, 0xe0, 0xeb, 0xbc, 0x5c, 0xf0, 0x39, 0x56, 0xf0, 0xc5, 0xd1,
0x05, 0xa7, 0x60, 0xeb, 0x53, 0xb8, 0x80, 0x18, 0x0d, 0xe0, 0x84, 0xd2, 0x19, 0xe1, 0xc4, 0x16,
0x26, 0xf2, 0xb3, 0xac, 0xdc, 0x0b, 0xa3, 0xcb, 0x55, 0x31, 0xeb, 0x53, 0x78, 0x14, 0x25, 0xea,
0x81, 0x96, 0x99, 0x4d, 0x47, 0xf2, 0xdb, 0x99, 0xdb, 0x9e, 0x9c, 0xe2, 0xf8, 0x58, 0xe6, 0x92,
0x65, 0x5a, 0xbe, 0xe8, 0xce, 0x9f, 0x1b, 0xd7, 0xf2, 0xa3, 0x7e, 0xcc, 0xa3, 0x52, 0xc6, 0x8e,
0x66, 0x3d, 0x31, 0xbc, 0x1e, 0x09, 0x78, 0x47, 0x77, 0x2d, 0xda, 0xa8, 0xef, 0x8c, 0x33, 0x76,
0x29, 0x98, 0x32, 0x76, 0x99, 0xc4, 0xc8, 0x87, 0x39, 0x45, 0xa3, 0xeb, 0xaf, 0xb8, 0xfd, 0x3e,
0x31, 0xc3, 0xde, 0xfc, 0x79, 0x56, 0xf0, 0x3b, 0xa3, 0x0b, 0x4e, 0x80, 0xd6, 0xa7, 0xf0, 0x48,
0xd2, 0x54, 0x7b, 0x1f, 0xf7, 0xad, 0x84, 0xcd, 0x68, 0x63, 0xd9, 0x6a, 0x12, 0x96, 0x6a, 0x6f,
0x4a, 0x23, 0x65, 0xab, 0x92, 0x06, 0x6d, 0xee, 0xab, 0xe3, 0xd8, 0xaa, 0x8a, 0x49, 0xd9, 0xaa,
0x9a, 0x4d, 0x57, 0xb7, 0xa1, 0x4f, 0x3c, 0xc6, 0x71, 0xdf, 0xb5, 0x1d, 0xed, 0x8d, 0xcc, 0xd5,
0xed, 0xa9, 0x4f, 0x3c, 0x51, 0x10, 0xd5, 0xa2, 0xab, 0x9b, 0x02, 0x53, 0x78, 0x1e, 0x92, 0x9d,
0x40, 0x3b, 0x59, 0xc4, 0x43, 0xb5, 0x14, 0x1e, 0x2a, 0xa0, 0x2b, 0x45, 0x24, 0xd8, 0x22, 0x74,
0x54, 0xb0, 0xe1, 0xf4, 0x88, 0xf6, 0x66, 0xe6, 0x4a, 0x21, 0xd1, 0x49, 0xca, 0x74, 0xa5, 0xc8,
0x22, 0xa1, 0x07, 0xf7, 0x48, 0x4e, 0x77, 0x64, 0x9c, 0x7a, 0x21, 0xf3, 0xe0, 0x2e, 0x51, 0x47,
0xaa, 0xf4, 0x0c, 0x92, 0x26, 0x40, 0x5f, 0x80, 0xea, 0xc0, 0x76, 0x7a, 0x9a, 0xc5, 0x88, 0x8e,
0x26, 0x88, 0x36, 0x6d, 0xa7, 0xb7, 0x3e, 0x85, 0x99, 0x0a, 0xba, 0x05, 0x30, 0xf0, 0x5c, 0x93,
0xf8, 0xfe, 0x06, 0x79, 0xa1, 0x11, 0x06, 0xd0, 0x93, 0x00, 0xae, 0xd0, 0xd9, 0x20, 0x74, 0x5d,
0x96, 0xf4, 0xd1, 0x1a, 0xcc, 0x88, 0x94, 0x98, 0xe5, 0x3b, 0x99, 0x9b, 0xbf, 0x90, 0x20, 0x0e,
0xe2, 0x28, 0x28, 0x7a, 0xf6, 0x11, 0x82, 0x55, 0xd7, 0x21, 0x5a, 0x2f, 0xf3, 0xec, 0x13, 0x92,
0x50, 0x15, 0xba, 0xc7, 0x92, 0x10, 0xf4, 0xb0, 0x1f, 0xec, 0x7a, 0xc4, 0xb0, 0xb6, 0x02, 0x23,
0x18, 0xfa, 0x9a, 0x93, 0xb9, 0x4d, 0xe3, 0x99, 0x9d, 0x27, 0x4c, 0x93, 0x6e, 0x41, 0x65, 0x0c,
0xda, 0x80, 0x36, 0x3d, 0x08, 0x3d, 0xb4, 0xf7, 0xec, 0x00, 0x13, 0xc3, 0xdc, 0x25, 0x96, 0xe6,
0x66, 0x1e, 0xa2, 0xe8, 0xb6, 0xb7, 0x23, 0xeb, 0xd1, 0xdd, 0x4a, 0x12, 0x8b, 0xd6, 0x61, 0x96,
0xca, 0xb6, 0x06, 0x86, 0x49, 0x9e, 0xfa, 0x46, 0x8f, 0x68, 0x83, 0x4c, 0x0b, 0x64, 0x6c, 0xb1,
0x16, 0xdd, 0xac, 0xa8, 0xb8, 0x90, 0xe9, 0xa1, 0x6b, 0x1a, 0x7d, 0xce, 0xf4, 0xcd, 0x7c, 0xa6,
0x58, 0x2b, 0x64, 0x8a, 0x25, 0x4a, 0x1b, 0x79, 0xdf, 0x5b, 0xda, 0x7e, 0x41, 0x1b, 0x85, 0x9e,
0xd2, 0x46, 0x21, 0xa3, 0x7c, 0x8e, 0x1b, 0xd8, 0x3b, 0xb6, 0x29, 0xe6, 0xaf, 0x63, 0x69, 0x5e,
0x26, 0xdf, 0x86, 0xa4, 0xd6, 0xd9, 0xe2, 0x81, 0xa1, 0x14, 0x16, 0x3d, 0x01, 0x24, 0xcb, 0x84,
0x51, 0xf9, 0x8c, 0x71, 0x61, 0x14, 0x63, 0x64, 0x59, 0x19, 0x78, 0x5a, 0xcb, 0x81, 0x71, 0x40,
0x8f, 0xb7, 0xcb, 0x9e, 0x6b, 0x58, 0xa6, 0xe1, 0x07, 0x5a, 0x90, 0x59, 0xcb, 0x4d, 0xae, 0xd6,
0x89, 0xf4, 0x68, 0x2d, 0x93, 0x58, 0xca, 0xb7, 0x47, 0xf6, 0xb6, 0x89, 0xe7, 0xef, 0xda, 0x03,
0x51, 0xc7, 0x61, 0x26, 0xdf, 0xa3, 0x48, 0x2d, 0xae, 0x61, 0x0a, 0x8b, 0x1e, 0xc0, 0xe1, 0xc1,
0xe5, 0x01, 0x37, 0x43, 0x41, 0xf7, 0x22, 0x73, 0x63, 0xbb, 0x79, 0x79, 0x53, 0xd8, 0x70, 0xc4,
0x96, 0x44, 0x2e, 0x37, 0xa0, 0xb6, 0x6f, 0xf4, 0x87, 0x44, 0xff, 0x5e, 0x0d, 0x1a, 0x22, 0xdc,
0xa9, 0x6f, 0x40, 0x95, 0xc5, 0x86, 0x8f, 0x41, 0xcd, 0x76, 0x2c, 0xf2, 0x92, 0x85, 0x95, 0x6b,
0x98, 0x27, 0xd0, 0x25, 0x68, 0x88, 0xf0, 0xa7, 0x88, 0x58, 0xe4, 0x05, 0xb3, 0x43, 0x35, 0xfd,
0x43, 0x68, 0x84, 0x31, 0xe2, 0x39, 0x68, 0x0d, 0x3c, 0x97, 0x5a, 0x46, 0xd7, 0x62, 0xb4, 0x2d,
0x1c, 0x0b, 0xd0, 0xbb, 0xd0, 0xb0, 0x44, 0x14, 0x9a, 0x53, 0xbf, 0xda, 0xe1, 0x61, 0xfb, 0x4e,
0x18, 0xb6, 0xef, 0x6c, 0xb1, 0xb0, 0x3d, 0x0e, 0xf5, 0xf4, 0x5f, 0x28, 0x41, 0x9d, 0x87, 0x8a,
0xf5, 0x7d, 0xa8, 0x8b, 0x2e, 0xba, 0x06, 0x75, 0x93, 0xc9, 0xb4, 0x64, 0x98, 0x58, 0xa9, 0xa1,
0x88, 0x3d, 0x63, 0xa1, 0x4c, 0x61, 0x3e, 0xf7, 0x08, 0xe5, 0x91, 0x30, 0xde, 0x83, 0x58, 0x28,
0xff, 0x8f, 0x95, 0xfb, 0x9f, 0x25, 0x98, 0x51, 0x23, 0xd0, 0x73, 0xd0, 0x32, 0xa3, 0x98, 0xb6,
0xe8, 0x5d, 0x53, 0x8a, 0x4f, 0x83, 0xd9, 0xb7, 0x89, 0x13, 0xb0, 0x68, 0x4d, 0x39, 0x73, 0x13,
0x90, 0x19, 0xf1, 0xee, 0xac, 0x44, 0x30, 0x2c, 0x51, 0xe8, 0xdf, 0x01, 0x88, 0x73, 0xd0, 0xc9,
0xc8, 0x2d, 0x6f, 0x18, 0x7b, 0x61, 0xf1, 0xb2, 0x48, 0xd2, 0xd8, 0x34, 0x82, 0x5d, 0xf1, 0xa1,
0x44, 0x16, 0xa1, 0x0b, 0x70, 0xc4, 0xb7, 0x7b, 0x8e, 0x11, 0x0c, 0x3d, 0xf2, 0x8c, 0x78, 0xf6,
0x8e, 0x4d, 0x2c, 0x16, 0xdc, 0x6a, 0xe2, 0x74, 0x86, 0xfe, 0x2f, 0x4d, 0xa8, 0xf3, 0xed, 0x96,
0xfe, 0xef, 0xe5, 0xc8, 0xc6, 0xf4, 0xbf, 0x28, 0x41, 0x8d, 0x47, 0x8d, 0x67, 0xa1, 0x6c, 0x87,
0x66, 0x56, 0xb6, 0x2d, 0x74, 0x4f, 0xb6, 0xaf, 0x4a, 0xc6, 0x5e, 0x24, 0x2b, 0x8a, 0xde, 0x79,
0x40, 0x0e, 0x9e, 0xd1, 0x39, 0x12, 0x19, 0x1d, 0x3a, 0x0e, 0x75, 0x7f, 0xb8, 0xdd, 0xb5, 0x7c,
0xad, 0x72, 0xb2, 0x72, 0xbe, 0x85, 0x45, 0x4a, 0xbf, 0x0f, 0xcd, 0x50, 0x19, 0xb5, 0xa1, 0xf2,
0x9c, 0x1c, 0x88, 0xc2, 0xe9, 0xbf, 0xe8, 0x82, 0x98, 0x6b, 0xd1, 0xb4, 0x49, 0xda, 0x36, 0x2f,
0x45, 0x4c, 0xc8, 0xaf, 0x43, 0x85, 0x6e, 0x70, 0x92, 0x4d, 0x98, 0x7c, 0x8a, 0xe4, 0xd6, 0x76,
0x05, 0x6a, 0x3c, 0x72, 0x9f, 0x2c, 0x03, 0x41, 0xf5, 0x39, 0x39, 0xe0, 0x7d, 0xd4, 0xc2, 0xec,
0xff, 0x5c, 0x92, 0x3f, 0xaf, 0xc0, 0x21, 0x39, 0xdc, 0xa9, 0xaf, 0x41, 0x65, 0xc9, 0x4a, 0x77,
0xbd, 0x06, 0x0d, 0x63, 0x27, 0x20, 0x5e, 0xf4, 0x81, 0x2c, 0x4c, 0x52, 0x2f, 0xc3, 0xb8, 0xd8,
0x38, 0xb7, 0x30, 0x4f, 0xe8, 0x1d, 0xa8, 0x8b, 0x28, 0x72, 0x92, 0x29, 0xd2, 0x2f, 0xcb, 0xfa,
0xf7, 0xa1, 0x19, 0x05, 0x85, 0x3f, 0x6d, 0xd9, 0x1e, 0x34, 0xa3, 0xe8, 0xef, 0x31, 0xa8, 0x05,
0x6e, 0x60, 0xf4, 0x19, 0x5d, 0x05, 0xf3, 0x04, 0x9d, 0x68, 0x0e, 0x79, 0x19, 0xac, 0x44, 0x5e,
0xb0, 0x82, 0x63, 0x01, 0x77, 0x72, 0x64, 0x9f, 0xe7, 0x56, 0x78, 0x6e, 0x24, 0x88, 0xcb, 0xac,
0xca, 0x65, 0x1e, 0x40, 0x5d, 0x84, 0x84, 0xa3, 0xfc, 0x92, 0x94, 0x8f, 0x96, 0xa0, 0xd6, 0xa3,
0xf9, 0x62, 0xd4, 0xdf, 0x4e, 0xb8, 0x08, 0xbe, 0xd3, 0x5b, 0x71, 0x9d, 0x80, 0x9a, 0xb1, 0x7a,
0xd2, 0xc5, 0x1c, 0x49, 0x87, 0xd0, 0xe3, 0xf1, 0x7d, 0x3e, 0xa3, 0x44, 0x4a, 0xff, 0x83, 0x12,
0xb4, 0xa2, 0xef, 0x21, 0xfa, 0x87, 0x79, 0x93, 0x67, 0x09, 0x66, 0x3c, 0xa1, 0x45, 0xbd, 0x43,
0x38, 0x85, 0x4e, 0x24, 0x6a, 0x82, 0x25, 0x1d, 0xac, 0x22, 0xf4, 0x5b, 0xb9, 0x83, 0xba, 0x00,
0x87, 0x42, 0xd5, 0x07, 0xb1, 0xe9, 0x29, 0x32, 0x5d, 0x8f, 0xd0, 0x6d, 0xa8, 0xd8, 0x16, 0xff,
0x3c, 0xdb, 0xc2, 0xf4, 0x5f, 0x7d, 0x07, 0x0e, 0xc9, 0x61, 0x55, 0xfd, 0x59, 0xf6, 0xec, 0xb9,
0x43, 0x8b, 0x91, 0x42, 0xb8, 0xe5, 0xc4, 0xde, 0x31, 0x6c, 0x42, 0xac, 0x82, 0x15, 0x80, 0xfe,
0x3b, 0x26, 0xd4, 0x58, 0x5f, 0xeb, 0x57, 0xb8, 0x9d, 0x5f, 0x80, 0x3a, 0x3b, 0x9f, 0x84, 0x1f,
0x8b, 0x8f, 0x65, 0x0d, 0x0c, 0x16, 0x3a, 0xfa, 0x0a, 0x4c, 0x4b, 0xd1, 0x74, 0x6a, 0x98, 0x2c,
0x23, 0x1a, 0xec, 0x30, 0x89, 0x74, 0x68, 0xd2, 0x35, 0x51, 0xf8, 0x49, 0xda, 0xcc, 0x28, 0xad,
0x9f, 0x86, 0xba, 0x38, 0x6f, 0xe9, 0xe2, 0xeb, 0x41, 0x37, 0xea, 0x8c, 0x28, 0xad, 0x7f, 0x15,
0x5a, 0x51, 0xd0, 0x1d, 0x3d, 0x86, 0x43, 0x22, 0xe8, 0xce, 0xcf, 0x0c, 0x54, 0x79, 0xb6, 0xc0,
0x88, 0xe8, 0x01, 0x81, 0xc5, 0xed, 0x3b, 0x4f, 0x0e, 0x06, 0x04, 0x2b, 0x04, 0xfa, 0xaf, 0x9c,
0x67, 0x1d, 0xac, 0x0f, 0xa0, 0x19, 0x45, 0x1a, 0x93, 0x9d, 0xbd, 0xc8, 0x3d, 0x60, 0xb9, 0x30,
0x4c, 0xce, 0xf1, 0xd4, 0xcf, 0x32, 0x47, 0xa9, 0x9f, 0x80, 0xca, 0x03, 0x72, 0x40, 0x27, 0x02,
0xf7, 0x97, 0x62, 0x22, 0x70, 0xbf, 0xd8, 0x85, 0xba, 0x88, 0xf8, 0x27, 0xcb, 0xbb, 0x08, 0xf5,
0x1d, 0xfe, 0x11, 0xa1, 0xc0, 0x33, 0x0a, 0x35, 0xfd, 0x0e, 0x4c, 0xcb, 0x71, 0xfe, 0x24, 0xdf,
0x49, 0x98, 0x36, 0xa5, 0x2f, 0x09, 0x7c, 0x18, 0x64, 0x91, 0x4e, 0x54, 0xab, 0x4b, 0x31, 0xac,
0x65, 0x9a, 0xdb, 0x9b, 0x99, 0xdd, 0x3e, 0xc2, 0xe8, 0x1e, 0xc0, 0xe1, 0x64, 0x40, 0x3f, 0x59,
0xd2, 0x79, 0x38, 0xbc, 0x9d, 0xf8, 0x7c, 0xc0, 0x5d, 0x5d, 0x52, 0xac, 0x77, 0xa1, 0xc6, 0x03,
0xae, 0x49, 0x8a, 0x4b, 0x50, 0x33, 0x58, 0x40, 0x97, 0x02, 0x67, 0xa5, 0x63, 0x9d, 0x5c, 0x4b,
0x06, 0xc5, 0x5c, 0x51, 0xb7, 0x61, 0x46, 0x8d, 0xe1, 0x26, 0x29, 0xd7, 0x61, 0x66, 0x5f, 0x89,
0x15, 0x73, 0xea, 0x85, 0x4c, 0x6a, 0x85, 0x0a, 0xab, 0x40, 0xfd, 0x17, 0xeb, 0x50, 0x65, 0x1f,
0x21, 0x92, 0x45, 0x5c, 0x87, 0x6a, 0x40, 0x5e, 0x86, 0x5b, 0xd1, 0x85, 0x91, 0x5f, 0x34, 0xf8,
0x49, 0x98, 0xe9, 0xa3, 0x2f, 0x42, 0xcd, 0x0f, 0x0e, 0xfa, 0xe1, 0xa7, 0xb3, 0x53, 0xa3, 0x81,
0x5b, 0x54, 0x15, 0x73, 0x04, 0x85, 0xb2, 0xb9, 0x20, 0x3e, 0x9a, 0x15, 0x40, 0xd9, 0x24, 0xc4,
0x1c, 0x81, 0xee, 0x40, 0xc3, 0xdc, 0x25, 0xe6, 0x73, 0x62, 0x89, 0xaf, 0x65, 0x67, 0x46, 0x83,
0x57, 0xb8, 0x32, 0x0e, 0x51, 0xb4, 0x6c, 0x93, 0x8d, 0x6e, 0x7d, 0x9c, 0xb2, 0xd9, 0x88, 0x63,
0x8e, 0x40, 0x6b, 0xd0, 0xb2, 0x4d, 0xd7, 0x59, 0xdb, 0x73, 0xbf, 0x61, 0x8b, 0xcf, 0x62, 0xe7,
0x46, 0xc3, 0xbb, 0xa1, 0x3a, 0x8e, 0x91, 0x21, 0x4d, 0x77, 0x8f, 0x9e, 0x2c, 0x9b, 0xe3, 0xd2,
0x30, 0x75, 0x1c, 0x23, 0xf5, 0x39, 0x31, 0x9e, 0xd9, 0x93, 0xfc, 0x1e, 0xd4, 0x58, 0x97, 0xa3,
0xf7, 0xe4, 0xec, 0x59, 0xa9, 0xa4, 0x5c, 0x8f, 0x25, 0x86, 0x2a, 0xe2, 0x61, 0xfd, 0xaf, 0xf2,
0x4c, 0x8f, 0xc3, 0x23, 0xc6, 0x8d, 0xf3, 0xbc, 0x01, 0x0d, 0x31, 0x14, 0x6a, 0x85, 0x9b, 0xa1,
0xc2, 0xeb, 0x50, 0xe3, 0x13, 0x33, 0xbb, 0x3d, 0x6f, 0x42, 0x2b, 0xea, 0xcc, 0xd1, 0x2a, 0xac,
0x77, 0x72, 0x54, 0x7e, 0xb5, 0x0c, 0x35, 0xfe, 0x31, 0x26, 0xed, 0x6a, 0xe5, 0x59, 0x70, 0x6a,
0xf4, 0xb7, 0x1d, 0x79, 0x1a, 0xdc, 0x63, 0xe7, 0x31, 0xba, 0xff, 0x8e, 0xee, 0x26, 0x9d, 0x2f,
0x40, 0x6f, 0x86, 0xfa, 0x38, 0x86, 0x16, 0x0c, 0xe7, 0x63, 0x68, 0x45, 0x28, 0xb4, 0xac, 0x0e,
0xe9, 0x85, 0x91, 0x43, 0x91, 0x2c, 0x52, 0x10, 0x7e, 0xb7, 0x04, 0x95, 0x55, 0x7b, 0x3f, 0xd5,
0x0f, 0x37, 0xc2, 0x59, 0x5d, 0xe4, 0x0e, 0x56, 0xed, 0x7d, 0x65, 0x52, 0xeb, 0x6b, 0xa1, 0xc5,
0xdd, 0x52, 0xab, 0x77, 0x76, 0xf4, 0x46, 0x2b, 0xa6, 0xe1, 0x15, 0xfb, 0x8d, 0x06, 0x54, 0xd9,
0x77, 0xce, 0x2c, 0x3f, 0x75, 0x30, 0x28, 0xae, 0x18, 0x8b, 0xa4, 0xb0, 0x05, 0x97, 0xe9, 0x73,
0x3f, 0x65, 0x04, 0xc5, 0x7e, 0x8a, 0x07, 0x86, 0xa8, 0x2a, 0xe6, 0x08, 0x5a, 0xe4, 0x9e, 0xbd,
0x47, 0x84, 0x9b, 0x2a, 0x28, 0xf2, 0x91, 0xbd, 0x47, 0x30, 0xd3, 0xa7, 0xb8, 0x5d, 0xc3, 0xdf,
0x15, 0x1e, 0xaa, 0x00, 0xb7, 0x6e, 0xf8, 0xbb, 0x98, 0xe9, 0x53, 0x9c, 0x43, 0x4f, 0x7e, 0xf5,
0x71, 0x70, 0xf4, 0x40, 0x88, 0x99, 0x3e, 0xc5, 0xf9, 0xf6, 0xb7, 0x88, 0xf0, 0x49, 0x05, 0xb8,
0x2d, 0xfb, 0x5b, 0x04, 0x33, 0xfd, 0xd8, 0x85, 0x37, 0xc7, 0xeb, 0x1a, 0xc9, 0x85, 0x3f, 0x81,
0xd9, 0x40, 0x89, 0xd6, 0x8b, 0x8f, 0xed, 0x17, 0x0a, 0xc6, 0x45, 0xc1, 0xe0, 0x04, 0x07, 0x9d,
0x04, 0xec, 0x9c, 0x9b, 0x3d, 0x09, 0x5e, 0x87, 0xda, 0x97, 0x6d, 0x2b, 0xd8, 0x55, 0xb3, 0x6b,
0x8a, 0xcb, 0xa3, 0xc3, 0x36, 0x91, 0xcb, 0x93, 0x47, 0x9d, 0xf3, 0xac, 0x42, 0x95, 0x9a, 0xcf,
0x64, 0x76, 0x1c, 0x5b, 0xdd, 0xa7, 0x72, 0xc0, 0x72, 0x47, 0x73, 0x9e, 0x39, 0xa8, 0x52, 0x0b,
0xc9, 0xe9, 0x92, 0x39, 0xa8, 0x52, 0xbb, 0xcb, 0xcf, 0xa5, 0xa3, 0xad, 0xe6, 0x56, 0xc2, 0xdc,
0xb3, 0x30, 0xab, 0x0e, 0x47, 0x0e, 0xcb, 0x9f, 0x35, 0xa0, 0xca, 0x2e, 0x0d, 0x24, 0x67, 0xe4,
0xcf, 0xc0, 0x0c, 0x1f, 0xbf, 0x65, 0xb1, 0x05, 0x2f, 0x67, 0xde, 0x19, 0x52, 0xaf, 0x22, 0x08,
0x13, 0x10, 0x10, 0xac, 0x32, 0x8c, 0xbf, 0xa9, 0x60, 0x54, 0x8a, 0x45, 0xde, 0x8a, 0x36, 0xaf,
0xd5, 0x82, 0x1b, 0x2b, 0x0c, 0xcb, 0xb7, 0xc0, 0xe1, 0x4e, 0x16, 0x2d, 0x43, 0x93, 0x2e, 0xad,
0xb4, 0xbb, 0xc4, 0xb4, 0x3d, 0x3b, 0x1a, 0xdf, 0x15, 0xda, 0x38, 0xc2, 0xd1, 0x85, 0xdd, 0x34,
0x3c, 0x8b, 0xd5, 0x4a, 0xcc, 0xe1, 0x73, 0xa3, 0x49, 0x56, 0x42, 0x75, 0x1c, 0x23, 0xd1, 0x03,
0x98, 0xb6, 0x48, 0x14, 0x0e, 0x10, 0x93, 0xfa, 0x0b, 0xa3, 0x89, 0x56, 0x63, 0x00, 0x96, 0xd1,
0xb4, 0x4e, 0xe1, 0x11, 0xd0, 0x2f, 0xdc, 0x6c, 0x30, 0xaa, 0xf8, 0x62, 0x5f, 0x8c, 0xd4, 0xcf,
0xc0, 0x8c, 0x32, 0x6e, 0x9f, 0xe9, 0xae, 0x43, 0x1e, 0x4b, 0xce, 0xb3, 0x18, 0x1d, 0x51, 0xde,
0x51, 0xb7, 0x1d, 0xb9, 0x27, 0x12, 0x01, 0x7c, 0x08, 0xcd, 0x70, 0x60, 0xd0, 0x5d, 0xb5, 0x0e,
0x6f, 0x15, 0xd7, 0x21, 0x1a, 0x53, 0xc1, 0xb6, 0x01, 0xad, 0x68, 0x84, 0xd0, 0x92, 0x4a, 0xf7,
0x76, 0x31, 0x5d, 0x3c, 0xba, 0x82, 0x0f, 0xc3, 0xb4, 0x34, 0x50, 0x68, 0x45, 0x65, 0x7c, 0xa7,
0x98, 0x51, 0x1e, 0xe6, 0x78, 0xd7, 0x13, 0x8d, 0x98, 0x3c, 0x2a, 0x95, 0x78, 0x54, 0xfe, 0xa4,
0x01, 0xcd, 0xe8, 0xa2, 0x4e, 0xc6, 0x19, 0x73, 0xe8, 0xf5, 0x0b, 0xcf, 0x98, 0x21, 0xbe, 0xf3,
0xd4, 0xeb, 0x63, 0x8a, 0xa0, 0x43, 0x1c, 0xd8, 0x41, 0x34, 0x55, 0xcf, 0x15, 0x43, 0x9f, 0x50,
0x75, 0xcc, 0x51, 0xe8, 0xb1, 0x6a, 0xe5, 0xd5, 0x11, 0x1f, 0x72, 0x15, 0x92, 0x5c, 0x4b, 0xef,
0x42, 0xcb, 0xa6, 0x5b, 0xbf, 0xf5, 0x78, 0xe5, 0x7d, 0xbb, 0x98, 0xae, 0x1b, 0x42, 0x70, 0x8c,
0xa6, 0x75, 0xdb, 0x31, 0xf6, 0xe9, 0xbc, 0x66, 0x64, 0xf5, 0x71, 0xeb, 0x76, 0x2f, 0x06, 0x61,
0x99, 0x01, 0xdd, 0x14, 0x7b, 0x97, 0x46, 0x81, 0x67, 0x89, 0xbb, 0x2a, 0xde, 0xbf, 0x7c, 0x90,
0x5a, 0x69, 0xf9, 0x34, 0xbe, 0x34, 0x06, 0xcb, 0xc8, 0xd5, 0x96, 0x8e, 0x20, 0xdf, 0x19, 0xb5,
0xc6, 0x1d, 0x41, 0x79, 0x77, 0xa4, 0x9f, 0x80, 0xca, 0x53, 0xaf, 0x9f, 0xbf, 0x56, 0xb3, 0xe1,
0xce, 0xc9, 0x3e, 0xa5, 0xce, 0x84, 0xfc, 0x0d, 0x7d, 0x34, 0x26, 0xb9, 0x3c, 0x52, 0xa7, 0xe7,
0x28, 0xbd, 0x27, 0x16, 0xf4, 0x6b, 0xea, 0x7c, 0x7b, 0x23, 0x31, 0xdf, 0xe8, 0x0c, 0xdb, 0xf4,
0x08, 0xbf, 0xab, 0x20, 0xad, 0xe4, 0xe3, 0xae, 0x93, 0xf7, 0xc3, 0xfd, 0xc7, 0x44, 0x9e, 0x22,
0xd9, 0xb7, 0x9c, 0xeb, 0x97, 0x4b, 0xd0, 0x8c, 0xee, 0x61, 0xa5, 0x83, 0xf0, 0x4d, 0xdb, 0x5f,
0x27, 0x86, 0x45, 0x3c, 0x31, 0x6f, 0xdf, 0x2a, 0xbc, 0xe0, 0xd5, 0xe9, 0x0a, 0x04, 0x8e, 0xb0,
0xfa, 0x49, 0x68, 0x86, 0xd2, 0x9c, 0x43, 0xd9, 0x8f, 0xca, 0x50, 0x17, 0x37, 0xb8, 0x92, 0x95,
0xb8, 0x0d, 0xf5, 0xbe, 0x71, 0xe0, 0x0e, 0xc3, 0x23, 0xd3, 0xd9, 0x82, 0x4b, 0x61, 0x9d, 0x87,
0x4c, 0x1b, 0x0b, 0x14, 0xfa, 0x12, 0xd4, 0xfa, 0xf6, 0x9e, 0x1d, 0x08, 0xf7, 0x71, 0xa6, 0x10,
0xce, 0xbe, 0xf5, 0x72, 0x0c, 0x2d, 0x9c, 0x5d, 0xdc, 0x08, 0xaf, 0xdd, 0x16, 0x16, 0xfe, 0x8c,
0x69, 0x63, 0x81, 0xd2, 0xef, 0x43, 0x9d, 0x57, 0x67, 0xb2, 0x45, 0x42, 0x6d, 0x49, 0x6c, 0xe9,
0xac, 0x6e, 0x39, 0xbb, 0xd2, 0x79, 0xa8, 0xf3, 0xc2, 0x73, 0xac, 0xe6, 0x87, 0xaf, 0xb1, 0xf3,
0x4e, 0x5f, 0x7f, 0x18, 0x7f, 0xe3, 0xfb, 0xf4, 0x9f, 0x2c, 0xf4, 0x27, 0x70, 0x78, 0xd5, 0x08,
0x8c, 0x6d, 0xc3, 0x27, 0x98, 0x98, 0xae, 0x67, 0x65, 0xb2, 0x7a, 0x3c, 0x4b, 0x04, 0xa2, 0xf3,
0x59, 0x85, 0xde, 0xe7, 0xa1, 0xc3, 0xff, 0x3d, 0xa1, 0xc3, 0x3f, 0xad, 0xe6, 0xc4, 0xf3, 0xc6,
0x89, 0x64, 0x50, 0x83, 0x4b, 0x05, 0xf4, 0x6e, 0xaa, 0x7b, 0xef, 0xd3, 0x05, 0x48, 0x65, 0xf3,
0x7d, 0x53, 0x8d, 0xe8, 0x15, 0x61, 0x95, 0x90, 0xde, 0xdd, 0x64, 0x48, 0xef, 0x6c, 0x01, 0x3a,
0x15, 0xd3, 0xbb, 0xa9, 0xc6, 0xf4, 0x8a, 0x4a, 0x97, 0x83, 0x7a, 0xff, 0xcf, 0xc2, 0x68, 0xbf,
0x95, 0x13, 0xf6, 0xf9, 0xa2, 0x1a, 0xf6, 0x19, 0x61, 0x35, 0x3f, 0xad, 0xb8, 0xcf, 0x6f, 0xd7,
0x73, 0xe2, 0x3e, 0x8b, 0x4a, 0xdc, 0x67, 0x44, 0xcd, 0x92, 0x81, 0x9f, 0x9b, 0x6a, 0xe0, 0xe7,
0x74, 0x01, 0x52, 0x89, 0xfc, 0x2c, 0x2a, 0x91, 0x9f, 0xa2, 0x42, 0xa5, 0xd0, 0xcf, 0xa2, 0x12,
0xfa, 0x29, 0x02, 0x4a, 0xb1, 0x9f, 0x45, 0x25, 0xf6, 0x53, 0x04, 0x94, 0x82, 0x3f, 0x8b, 0x4a,
0xf0, 0xa7, 0x08, 0x28, 0x45, 0x7f, 0x6e, 0xaa, 0xd1, 0x9f, 0xe2, 0xfe, 0x91, 0x06, 0xfd, 0xf3,
0x40, 0xcd, 0x7f, 0x63, 0xa0, 0xe6, 0xd7, 0x2b, 0x39, 0x01, 0x18, 0x9c, 0x1d, 0x80, 0xb9, 0x90,
0x3f, 0x92, 0xc5, 0x11, 0x98, 0xf1, 0x57, 0x81, 0x74, 0x08, 0xe6, 0xbd, 0x44, 0x08, 0xe6, 0x4c,
0x01, 0x58, 0x8d, 0xc1, 0xfc, 0x9f, 0x09, 0x32, 0xfc, 0x51, 0x7d, 0xc4, 0x79, 0xfa, 0x86, 0x7c,
0x9e, 0x1e, 0xb1, 0x92, 0xa5, 0x0f, 0xd4, 0xb7, 0xd5, 0x03, 0xf5, 0xf9, 0x31, 0xb0, 0xca, 0x89,
0x7a, 0x33, 0xeb, 0x44, 0xdd, 0x19, 0x83, 0x25, 0xf7, 0x48, 0x7d, 0x3f, 0x7d, 0xa4, 0xbe, 0x30,
0x06, 0x5f, 0xe6, 0x99, 0x7a, 0x33, 0xeb, 0x4c, 0x3d, 0x4e, 0xed, 0x72, 0x0f, 0xd5, 0x5f, 0x52,
0x0e, 0xd5, 0xe7, 0xc6, 0xe9, 0xae, 0x78, 0x71, 0xf8, 0x4a, 0xce, 0xa9, 0xfa, 0xdd, 0x71, 0x68,
0x46, 0x07, 0xb1, 0x3f, 0x3f, 0x17, 0xab, 0xc5, 0xfc, 0xe1, 0x1b, 0xd0, 0x0c, 0xef, 0xd3, 0xe8,
0xdf, 0x84, 0x46, 0xf8, 0x6c, 0x27, 0x39, 0x73, 0x8e, 0x47, 0x87, 0x3a, 0xbe, 0x7b, 0x16, 0x29,
0x74, 0x1b, 0xaa, 0xf4, 0x3f, 0x31, 0x2d, 0xde, 0x1a, 0xef, 0xde, 0x0e, 0x2d, 0x04, 0x33, 0x9c,
0xfe, 0xe3, 0x63, 0x00, 0xd2, 0x6b, 0x86, 0x71, 0x8b, 0x7d, 0x9f, 0x3a, 0xb3, 0x7e, 0x40, 0x3c,
0x76, 0x5f, 0xab, 0xf0, 0xb6, 0x7f, 0x5c, 0x02, 0xb5, 0x96, 0x80, 0x78, 0x58, 0xc0, 0xd1, 0x23,
0x68, 0x86, 0x81, 0x54, 0xad, 0xca, 0xa8, 0xde, 0x1d, 0x9b, 0x2a, 0x0c, 0xed, 0xe1, 0x88, 0x02,
0x2d, 0x41, 0xd5, 0x77, 0xbd, 0x40, 0xab, 0x31, 0xaa, 0x77, 0xc6, 0xa6, 0xda, 0x72, 0xbd, 0x00,
0x33, 0x28, 0x6f, 0x9a, 0xf4, 0x58, 0x74, 0x92, 0xa6, 0x29, 0x1e, 0xfb, 0xdf, 0x2a, 0x91, 0x0f,
0x5d, 0x11, 0xb3, 0x91, 0xdb, 0xd0, 0xc5, 0xf1, 0x47, 0x49, 0x9e, 0x95, 0x48, 0x6c, 0x82, 0xf8,
0x48, 0xf0, 0xfd, 0xcd, 0x5b, 0xd0, 0x36, 0xdd, 0x7d, 0xe2, 0xe1, 0xf8, 0x26, 0x93, 0xb8, 0x6c,
0x96, 0x92, 0x23, 0x1d, 0x9a, 0xbb, 0xb6, 0x45, 0xba, 0xa6, 0xf0, 0x7f, 0x4d, 0x1c, 0xa5, 0xd1,
0x03, 0x68, 0xb2, 0x18, 0x7b, 0x18, 0xe1, 0x9f, 0xac, 0x92, 0x3c, 0xd4, 0x1f, 0x12, 0xd0, 0x82,
0x58, 0xe1, 0xf7, 0xec, 0x80, 0xf5, 0x61, 0x13, 0x47, 0x69, 0x5a, 0x61, 0x76, 0x5d, 0x4c, 0xae,
0x70, 0x83, 0x57, 0x38, 0x29, 0x47, 0x57, 0xe1, 0x15, 0x26, 0x4b, 0x1c, 0x31, 0x79, 0xa8, 0xbe,
0x89, 0xb3, 0x33, 0xd9, 0xf5, 0x38, 0xa3, 0xc7, 0xaf, 0x86, 0xb3, 0xe0, 0x5d, 0x0d, 0xc7, 0x02,
0x74, 0x01, 0x8e, 0x58, 0x64, 0xc7, 0x18, 0xf6, 0x83, 0x27, 0x64, 0x6f, 0xd0, 0x37, 0x02, 0xd2,
0xb5, 0xd8, 0x7b, 0xd5, 0x16, 0x4e, 0x67, 0xa0, 0x4b, 0x70, 0x54, 0x08, 0xf9, 0x34, 0xa6, 0xa3,
0xd1, 0xb5, 0xd8, 0xf3, 0xcd, 0x16, 0xce, 0xca, 0xd2, 0x7f, 0x58, 0xa5, 0x83, 0xce, 0x4c, 0xfb,
0x7d, 0xa8, 0x18, 0x96, 0x25, 0x96, 0xcd, 0x2b, 0x13, 0x4e, 0x10, 0xf1, 0x24, 0x9b, 0x32, 0xa0,
0xcd, 0xe8, 0x66, 0x1d, 0x5f, 0x38, 0xaf, 0x4f, 0xca, 0x15, 0x3d, 0xa3, 0x17, 0x3c, 0x94, 0x71,
0xc8, 0xef, 0x76, 0x57, 0x7e, 0x32, 0xc6, 0xe8, 0xca, 0xb7, 0xe0, 0x41, 0xf7, 0xa1, 0xca, 0x6a,
0xc8, 0x17, 0xd6, 0xab, 0x93, 0xf2, 0x3d, 0xe2, 0xf5, 0x63, 0x1c, 0xba, 0xc9, 0xef, 0xbe, 0x49,
0xf7, 0x2a, 0x4b, 0xea, 0xbd, 0xca, 0x65, 0xa8, 0xd9, 0x01, 0xd9, 0x4b, 0x5f, 0xb3, 0x1d, 0x69,
0xaa, 0xc2, 0xf3, 0x70, 0xe8, 0xc8, 0xeb, 0x7e, 0x1f, 0x46, 0x57, 0xae, 0x93, 0xfe, 0xf0, 0x2e,
0x54, 0x29, 0x3c, 0xb5, 0x97, 0x1c, 0xa7, 0x60, 0x86, 0xd4, 0x2f, 0x43, 0x95, 0x36, 0x76, 0x44,
0xeb, 0x44, 0x7d, 0xca, 0x51, 0x7d, 0x96, 0xa7, 0xa1, 0xe5, 0x0e, 0x88, 0xc7, 0x26, 0x86, 0xfe,
0xcf, 0x55, 0xe9, 0x52, 0x5c, 0x57, 0xb6, 0xb1, 0x6b, 0x13, 0x7b, 0x4e, 0xd9, 0xca, 0x70, 0xc2,
0xca, 0x6e, 0x4c, 0xce, 0x96, 0xb2, 0x33, 0x9c, 0xb0, 0xb3, 0x9f, 0x80, 0x33, 0x65, 0x69, 0x0f,
0x15, 0x4b, 0xbb, 0x3e, 0x39, 0xa3, 0x62, 0x6b, 0xa4, 0xc8, 0xd6, 0x56, 0x55, 0x5b, 0xeb, 0x8c,
0x37, 0xe4, 0xd1, 0xd2, 0x34, 0x86, 0xb5, 0x7d, 0x35, 0xd7, 0xda, 0x96, 0x15, 0x6b, 0x9b, 0xb4,
0xe8, 0xcf, 0xc8, 0xde, 0xfe, 0xbe, 0x0a, 0x55, 0xba, 0x3c, 0xa2, 0x35, 0xd9, 0xd6, 0xde, 0x9d,
0x68, 0x69, 0x95, 0xed, 0x6c, 0x23, 0x61, 0x67, 0x57, 0x27, 0x63, 0x4a, 0xd9, 0xd8, 0x46, 0xc2,
0xc6, 0x26, 0xe4, 0x4b, 0xd9, 0xd7, 0xba, 0x62, 0x5f, 0x97, 0x27, 0x63, 0x53, 0x6c, 0xcb, 0x28,
0xb2, 0xad, 0xbb, 0xaa, 0x6d, 0x8d, 0xb9, 0x7b, 0x63, 0x7b, 0x95, 0x31, 0xec, 0xea, 0x83, 0x5c,
0xbb, 0xba, 0xad, 0xd8, 0xd5, 0x24, 0xc5, 0x7e, 0x46, 0x36, 0x75, 0x95, 0x6f, 0x3a, 0xc5, 0x3d,
0xe3, 0x31, 0x37, 0x9d, 0xfa, 0x35, 0x68, 0xc5, 0xcf, 0xc1, 0x33, 0x6e, 0xe1, 0x73, 0xb5, 0xb0,
0xd4, 0x30, 0xa9, 0x5f, 0x81, 0x56, 0xfc, 0xc4, 0x3b, 0xa3, 0x2c, 0x9f, 0x65, 0x0a, 0x94, 0x48,
0xe9, 0x6b, 0x70, 0x24, 0xfd, 0x00, 0x35, 0x23, 0x0e, 0x2f, 0x5d, 0x21, 0x0f, 0x5f, 0x9c, 0x48,
0x22, 0xfd, 0x05, 0xcc, 0x26, 0x9e, 0x94, 0x4e, 0xcc, 0x81, 0xae, 0x48, 0x5b, 0xe4, 0x8a, 0x38,
0x83, 0x67, 0x5f, 0x8a, 0x8f, 0x37, 0xc2, 0xfa, 0x2a, 0xcc, 0x16, 0x54, 0x7e, 0x9c, 0x3b, 0xf1,
0x5f, 0x87, 0xe9, 0x51, 0x75, 0xff, 0x0c, 0xee, 0xec, 0x07, 0xd0, 0x4e, 0x3d, 0x87, 0x4f, 0x16,
0xb3, 0x09, 0xd0, 0x8b, 0x74, 0x84, 0xd1, 0x5e, 0x9a, 0xe0, 0x85, 0x02, 0xc3, 0x61, 0x89, 0x43,
0xff, 0xfd, 0x12, 0x1c, 0x49, 0xbf, 0x85, 0x1f, 0xf7, 0xf0, 0xa3, 0x41, 0x83, 0x71, 0x45, 0x0f,
0x3b, 0xc2, 0x24, 0x7a, 0x04, 0x87, 0xfc, 0xbe, 0x6d, 0x92, 0x95, 0x5d, 0xc3, 0xe9, 0x11, 0x5f,
0x9c, 0x68, 0x0a, 0xde, 0xb3, 0x6f, 0xc5, 0x08, 0xac, 0xc0, 0xf5, 0x17, 0x30, 0x2d, 0x65, 0xa2,
0x5b, 0x50, 0x76, 0x07, 0xa9, 0x7b, 0x8d, 0xf9, 0x9c, 0x8f, 0xc3, 0xf9, 0x86, 0xcb, 0xee, 0x20,
0x3d, 0x25, 0xe5, 0xe9, 0x5b, 0x51, 0xa6, 0xaf, 0xfe, 0x00, 0x8e, 0xa4, 0x9f, 0x9b, 0x27, 0xbb,
0xe7, 0x6c, 0x2a, 0x4a, 0xc0, 0xbb, 0x29, 0x79, 0xe4, 0x5f, 0x84, 0xc3, 0xc9, 0x47, 0xe4, 0x19,
0x8f, 0x6e, 0xe2, 0xb7, 0x4b, 0x61, 0xb8, 0x7e, 0xe1, 0xd7, 0x4a, 0x30, 0xab, 0x36, 0x04, 0x1d,
0x07, 0xa4, 0x4a, 0x36, 0x5c, 0x87, 0xb4, 0xa7, 0xd0, 0x2b, 0x70, 0x44, 0x95, 0x2f, 0x59, 0x56,
0xbb, 0x94, 0x56, 0xa7, 0x6e, 0xab, 0x5d, 0x46, 0x1a, 0x1c, 0x4b, 0xf4, 0x10, 0x73, 0xa2, 0xed,
0x0a, 0x7a, 0x0d, 0x5e, 0x49, 0xe6, 0x0c, 0xfa, 0x86, 0x49, 0xda, 0x55, 0xfd, 0x5f, 0xcb, 0x50,
0x7d, 0xea, 0x13, 0x4f, 0xff, 0xa7, 0x72, 0xf8, 0x4a, 0xe3, 0x06, 0x54, 0xd9, 0xfb, 0x6e, 0xe9,
0xd1, 0x62, 0x29, 0xf1, 0x68, 0x51, 0x79, 0xf8, 0x16, 0x3f, 0x5a, 0xbc, 0x01, 0x55, 0xf6, 0xa2,
0x7b, 0x72, 0xe4, 0x2f, 0x95, 0xa0, 0x15, 0xbf, 0xae, 0x9e, 0x18, 0x2f, 0xbf, 0x0a, 0x29, 0xab,
0xaf, 0x42, 0xde, 0x82, 0x9a, 0xc7, 0xde, 0x6f, 0x70, 0x2f, 0x93, 0x7c, 0x6b, 0xc2, 0x0a, 0xc4,
0x5c, 0x45, 0x27, 0x30, 0x2d, 0xbf, 0x1d, 0x9f, 0xbc, 0x1a, 0xa7, 0xc5, 0x0f, 0xc7, 0x74, 0x2d,
0x7f, 0xc9, 0xf3, 0x8c, 0x03, 0x61, 0x98, 0xaa, 0x50, 0x9f, 0x83, 0xea, 0xa6, 0xed, 0xf4, 0xb2,
0xdf, 0x8a, 0xea, 0xdf, 0x2f, 0x41, 0x43, 0x5c, 0xde, 0xd5, 0x17, 0xa1, 0xb2, 0x41, 0x5e, 0xd0,
0x8a, 0x88, 0x6b, 0xc3, 0xa9, 0x8a, 0x3c, 0x62, 0xad, 0x10, 0xfa, 0x38, 0x54, 0xd3, 0x6f, 0x46,
0xcb, 0xe4, 0xe4, 0xd8, 0x1b, 0x50, 0x65, 0x4f, 0xbe, 0x27, 0x47, 0xfe, 0x6e, 0x13, 0xea, 0xfc,
0xc1, 0xa5, 0xfe, 0xdd, 0x26, 0xd4, 0xf9, 0x33, 0x70, 0x74, 0x1b, 0x1a, 0xfe, 0x70, 0x6f, 0xcf,
0xf0, 0x0e, 0xb4, 0xec, 0x9f, 0x0c, 0x54, 0x5e, 0x8d, 0x77, 0xb6, 0xb8, 0x2e, 0x0e, 0x41, 0xe8,
0x1a, 0x54, 0x4d, 0x63, 0x87, 0xa4, 0x3e, 0xe7, 0x66, 0x81, 0x57, 0x8c, 0x1d, 0x82, 0x99, 0x3a,
0xba, 0x0b, 0x4d, 0x31, 0x2c, 0xbe, 0x88, 0xe7, 0x8c, 0x2e, 0x37, 0x1c, 0xcc, 0x08, 0xa5, 0xdf,
0x87, 0x86, 0xa8, 0x0c, 0xba, 0x13, 0x3d, 0x37, 0x4d, 0x46, 0x9e, 0x33, 0x9b, 0x70, 0xe0, 0x98,
0x89, 0x87, 0xa7, 0x7f, 0x59, 0x86, 0x2a, 0xad, 0xdc, 0xa7, 0x66, 0x42, 0xf3, 0x00, 0x7d, 0xc3,
0x0f, 0x36, 0x87, 0xfd, 0x3e, 0xb1, 0xc4, 0x43, 0x3a, 0x49, 0x82, 0xce, 0xc3, 0x61, 0x9e, 0xf2,
0x77, 0xb7, 0x86, 0xa6, 0x49, 0xa2, 0xd7, 0xa0, 0x49, 0x31, 0x5a, 0x82, 0x1a, 0xfb, 0x61, 0x32,
0xb1, 0x2b, 0x7c, 0xbb, 0xb0, 0x67, 0x3b, 0x9b, 0xb6, 0x23, 0x6a, 0xc3, 0x91, 0xba, 0x0b, 0xad,
0x48, 0x46, 0x27, 0xe1, 0xc0, 0x76, 0x1c, 0xdb, 0xe9, 0x09, 0x8b, 0x0e, 0x93, 0x74, 0xd1, 0xa1,
0xff, 0x8a, 0xfa, 0xd6, 0xb0, 0x48, 0x51, 0xf9, 0x8e, 0x61, 0xf7, 0x45, 0x15, 0x6b, 0x58, 0xa4,
0x28, 0xd3, 0x50, 0x3c, 0x9e, 0xaf, 0xb2, 0x06, 0x86, 0x49, 0xfd, 0xe3, 0x52, 0xf4, 0xe6, 0x3a,
0xeb, 0x0d, 0x66, 0x2a, 0x96, 0x34, 0x27, 0x07, 0xb4, 0xf9, 0x82, 0x20, 0x85, 0xa8, 0x8f, 0x43,
0xdd, 0x75, 0xfa, 0xb6, 0x43, 0x44, 0xec, 0x48, 0xa4, 0x12, 0x7d, 0x5c, 0x4b, 0xf5, 0xb1, 0xc8,
0x5f, 0xb3, 0x6c, 0x5a, 0xc5, 0x7a, 0x9c, 0xcf, 0x25, 0xe8, 0x3d, 0x68, 0x58, 0x64, 0xdf, 0x36,
0x89, 0xaf, 0x35, 0x98, 0xe9, 0x9d, 0x1a, 0xd9, 0xb7, 0xab, 0x4c, 0x17, 0x87, 0x18, 0x3d, 0x80,
0x3a, 0x17, 0x45, 0x4d, 0x2a, 0x49, 0x4d, 0x8a, 0x2b, 0x5d, 0x1e, 0x51, 0xe9, 0x4a, 0x41, 0xa5,
0xab, 0xc9, 0x4a, 0x2f, 0x58, 0x00, 0xb1, 0xb9, 0xa1, 0x69, 0x68, 0x3c, 0x75, 0x9e, 0x3b, 0xee,
0x0b, 0xa7, 0x3d, 0x45, 0x13, 0x8f, 0x77, 0x76, 0x68, 0x29, 0xed, 0x12, 0x4d, 0x50, 0x3d, 0xdb,
0xe9, 0xb5, 0xcb, 0x08, 0xa0, 0x4e, 0x13, 0xc4, 0x6a, 0x57, 0xe8, 0xff, 0xf7, 0xd8, 0xf8, 0xb5,
0xab, 0xe8, 0x55, 0x38, 0xda, 0x75, 0x4c, 0x77, 0x6f, 0x60, 0x04, 0xf6, 0x76, 0x9f, 0x3c, 0x23,
0x9e, 0x6f, 0xbb, 0x4e, 0xbb, 0xa6, 0xff, 0x47, 0x89, 0x7f, 0xf5, 0xd5, 0xef, 0xc2, 0x21, 0xe5,
0xd7, 0x1c, 0x34, 0x68, 0xf8, 0x03, 0xfe, 0xe3, 0xad, 0x62, 0xdf, 0x2d, 0x92, 0xcc, 0x4a, 0xf8,
0xeb, 0x77, 0xb1, 0x65, 0xe1, 0x29, 0xfd, 0x1e, 0x80, 0xf4, 0x1b, 0x0e, 0xf3, 0x00, 0xdb, 0x07,
0x01, 0xf1, 0xf9, 0xef, 0x37, 0x50, 0x8a, 0x2a, 0x96, 0x24, 0x32, 0x7f, 0x59, 0xe1, 0xd7, 0xaf,
0x03, 0x48, 0xbf, 0xe0, 0x40, 0xe7, 0x0f, 0x4d, 0x2d, 0x27, 0xc9, 0x92, 0x62, 0xbd, 0x23, 0x5a,
0x10, 0xfe, 0x56, 0x43, 0x58, 0x03, 0x1e, 0xa5, 0x93, 0x6b, 0xc0, 0x24, 0xfa, 0x1a, 0x40, 0xfc,
0x73, 0x05, 0xfa, 0x62, 0xe4, 0xa2, 0xdf, 0x81, 0xaa, 0x65, 0x04, 0x86, 0xf0, 0x8e, 0xaf, 0x25,
0x56, 0xa8, 0x18, 0x82, 0x99, 0x9a, 0xfe, 0x7b, 0x25, 0x38, 0x24, 0xff, 0x34, 0x83, 0xfe, 0x3e,
0x54, 0xd9, 0x6f, 0x3b, 0xdc, 0x81, 0x43, 0xf2, 0x6f, 0x33, 0xa4, 0x7e, 0xd9, 0x96, 0xf3, 0xc9,
0x50, 0xac, 0x00, 0xf4, 0x6e, 0x54, 0xa5, 0x4f, 0x4d, 0x75, 0x09, 0x1a, 0xe2, 0xa7, 0x1e, 0xf4,
0x33, 0xd0, 0x8a, 0x7f, 0xd9, 0x81, 0xfa, 0x08, 0x2e, 0x0f, 0x47, 0x59, 0x24, 0xe9, 0xf6, 0xb5,
0x15, 0xfd, 0xfc, 0x82, 0xfe, 0x51, 0x54, 0x95, 0x7c, 0xbb, 0x58, 0x54, 0x7e, 0x03, 0x60, 0x76,
0xc4, 0x8f, 0x39, 0xa8, 0x2e, 0x74, 0xe1, 0x66, 0xb8, 0x4c, 0xa1, 0x19, 0x68, 0xad, 0xb8, 0x8e,
0x43, 0xcc, 0x80, 0x58, 0xed, 0x29, 0x74, 0x18, 0xa6, 0x37, 0xdc, 0x60, 0xd3, 0xf5, 0x7d, 0x6a,
0xb4, 0xed, 0x12, 0x6a, 0xb3, 0xae, 0x8e, 0x55, 0xca, 0x0b, 0xdf, 0x86, 0x19, 0x4c, 0xfc, 0x81,
0xeb, 0xf8, 0xe4, 0xa7, 0xf5, 0xe3, 0xc7, 0xb9, 0x3f, 0x63, 0xbc, 0xf0, 0xfd, 0x0a, 0xd4, 0xd8,
0xda, 0xab, 0xff, 0x71, 0x25, 0xda, 0x25, 0x64, 0xdc, 0xcc, 0x8a, 0xef, 0x4f, 0xcc, 0x4a, 0x83,
0xa6, 0xac, 0xda, 0x72, 0x10, 0xfe, 0xb2, 0x7c, 0x6f, 0x62, 0x56, 0xfa, 0x55, 0x17, 0x15, 0xa1,
0xdc, 0x97, 0xf8, 0x12, 0x34, 0x07, 0x9e, 0xdb, 0xf3, 0xe8, 0xf6, 0xa0, 0x9a, 0xf8, 0x2d, 0x0d,
0x15, 0xb6, 0x29, 0xd4, 0x70, 0x04, 0xd0, 0x37, 0xa0, 0x19, 0x4a, 0x73, 0x5e, 0x8b, 0x23, 0xa8,
0x5a, 0xae, 0x70, 0x71, 0x15, 0xcc, 0xfe, 0xa7, 0xfd, 0x22, 0x7a, 0x30, 0xdc, 0xda, 0x8b, 0xe4,
0xc2, 0xd7, 0xc4, 0x77, 0xad, 0x19, 0x68, 0xad, 0x7a, 0xee, 0x80, 0xbd, 0x17, 0x6e, 0x4f, 0x51,
0x87, 0xd4, 0xdd, 0x1b, 0xb8, 0x5e, 0xd0, 0x2e, 0xd1, 0xff, 0xd7, 0x5e, 0xb2, 0xff, 0xcb, 0xe8,
0x10, 0x34, 0xb7, 0x8c, 0x7d, 0x42, 0xd5, 0xda, 0x15, 0x84, 0xe8, 0xa9, 0x92, 0xc5, 0xf2, 0xc5,
0xc2, 0xd2, 0xae, 0x52, 0xa2, 0x47, 0x76, 0x8f, 0x6f, 0x96, 0xdb, 0xb5, 0x85, 0xa5, 0xf0, 0xfe,
0x42, 0x13, 0xaa, 0x62, 0x73, 0x3e, 0x0d, 0x0d, 0x3c, 0x64, 0xab, 0x5b, 0xbb, 0x44, 0xc5, 0x74,
0xcb, 0xc4, 0xa9, 0x57, 0x0c, 0xc7, 0x24, 0x7d, 0xe6, 0x11, 0x5b, 0x50, 0x5b, 0xf3, 0x3c, 0xd7,
0x6b, 0x57, 0x97, 0xe7, 0xfe, 0xea, 0xe3, 0xf9, 0xd2, 0x0f, 0x3e, 0x9e, 0x2f, 0xfd, 0xe8, 0xe3,
0xf9, 0xd2, 0x6f, 0x7e, 0x32, 0x3f, 0xf5, 0x83, 0x4f, 0xe6, 0xa7, 0xfe, 0xf1, 0x93, 0xf9, 0xa9,
0x0f, 0xcb, 0x83, 0xed, 0xed, 0x3a, 0xfb, 0xf0, 0x7c, 0xe5, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff,
0x18, 0xd9, 0x91, 0xb5, 0xba, 0x5b, 0x00, 0x00,
}
func (m *Event) Marshal() (dAtA []byte, err error) {
@ -20674,7 +20682,14 @@ func (m *EventP2PStatusUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) {
if m.Status != 0 {
i = encodeVarintEvents(dAtA, i, uint64(m.Status))
i--
dAtA[i] = 0x8
dAtA[i] = 0x10
}
if len(m.SpaceId) > 0 {
i -= len(m.SpaceId)
copy(dAtA[i:], m.SpaceId)
i = encodeVarintEvents(dAtA, i, uint64(len(m.SpaceId)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
@ -24847,6 +24862,10 @@ func (m *EventP2PStatusUpdate) Size() (n int) {
}
var l int
_ = l
l = len(m.SpaceId)
if l > 0 {
n += 1 + l + sovEvents(uint64(l))
}
if m.Status != 0 {
n += 1 + sovEvents(uint64(m.Status))
}
@ -47374,6 +47393,38 @@ func (m *EventP2PStatusUpdate) Unmarshal(dAtA []byte) error {
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SpaceId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvents
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthEvents
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SpaceId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType)
}

View file

@ -1066,12 +1066,13 @@ message Event {
message P2PStatus {
message Update {
Status status = 1;
string spaceId = 1;
Status status = 2;
}
enum Status {
Possible = 0;
Connected = 1;
Connected = 0;
NotPossible = 1;
NotConnected = 2;
}
}

View file

@ -0,0 +1,311 @@
// Code generated by mockery. DO NOT EDIT.
package mock_clientserver
import (
app "github.com/anyproto/any-sync/app"
context "context"
mock "github.com/stretchr/testify/mock"
)
// MockClientServer is an autogenerated mock type for the ClientServer type
type MockClientServer struct {
mock.Mock
}
type MockClientServer_Expecter struct {
mock *mock.Mock
}
func (_m *MockClientServer) EXPECT() *MockClientServer_Expecter {
return &MockClientServer_Expecter{mock: &_m.Mock}
}
// Close provides a mock function with given fields: ctx
func (_m *MockClientServer) Close(ctx context.Context) error {
ret := _m.Called(ctx)
if len(ret) == 0 {
panic("no return value specified for Close")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
r0 = rf(ctx)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockClientServer_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
type MockClientServer_Close_Call struct {
*mock.Call
}
// Close is a helper method to define mock.On call
// - ctx context.Context
func (_e *MockClientServer_Expecter) Close(ctx interface{}) *MockClientServer_Close_Call {
return &MockClientServer_Close_Call{Call: _e.mock.On("Close", ctx)}
}
func (_c *MockClientServer_Close_Call) Run(run func(ctx context.Context)) *MockClientServer_Close_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context))
})
return _c
}
func (_c *MockClientServer_Close_Call) Return(err error) *MockClientServer_Close_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockClientServer_Close_Call) RunAndReturn(run func(context.Context) error) *MockClientServer_Close_Call {
_c.Call.Return(run)
return _c
}
// Init provides a mock function with given fields: a
func (_m *MockClientServer) Init(a *app.App) error {
ret := _m.Called(a)
if len(ret) == 0 {
panic("no return value specified for Init")
}
var r0 error
if rf, ok := ret.Get(0).(func(*app.App) error); ok {
r0 = rf(a)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockClientServer_Init_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Init'
type MockClientServer_Init_Call struct {
*mock.Call
}
// Init is a helper method to define mock.On call
// - a *app.App
func (_e *MockClientServer_Expecter) Init(a interface{}) *MockClientServer_Init_Call {
return &MockClientServer_Init_Call{Call: _e.mock.On("Init", a)}
}
func (_c *MockClientServer_Init_Call) Run(run func(a *app.App)) *MockClientServer_Init_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*app.App))
})
return _c
}
func (_c *MockClientServer_Init_Call) Return(err error) *MockClientServer_Init_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockClientServer_Init_Call) RunAndReturn(run func(*app.App) error) *MockClientServer_Init_Call {
_c.Call.Return(run)
return _c
}
// Name provides a mock function with given fields:
func (_m *MockClientServer) Name() string {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Name")
}
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// MockClientServer_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name'
type MockClientServer_Name_Call struct {
*mock.Call
}
// Name is a helper method to define mock.On call
func (_e *MockClientServer_Expecter) Name() *MockClientServer_Name_Call {
return &MockClientServer_Name_Call{Call: _e.mock.On("Name")}
}
func (_c *MockClientServer_Name_Call) Run(run func()) *MockClientServer_Name_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockClientServer_Name_Call) Return(name string) *MockClientServer_Name_Call {
_c.Call.Return(name)
return _c
}
func (_c *MockClientServer_Name_Call) RunAndReturn(run func() string) *MockClientServer_Name_Call {
_c.Call.Return(run)
return _c
}
// Port provides a mock function with given fields:
func (_m *MockClientServer) Port() int {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Port")
}
var r0 int
if rf, ok := ret.Get(0).(func() int); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(int)
}
return r0
}
// MockClientServer_Port_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Port'
type MockClientServer_Port_Call struct {
*mock.Call
}
// Port is a helper method to define mock.On call
func (_e *MockClientServer_Expecter) Port() *MockClientServer_Port_Call {
return &MockClientServer_Port_Call{Call: _e.mock.On("Port")}
}
func (_c *MockClientServer_Port_Call) Run(run func()) *MockClientServer_Port_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockClientServer_Port_Call) Return(_a0 int) *MockClientServer_Port_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockClientServer_Port_Call) RunAndReturn(run func() int) *MockClientServer_Port_Call {
_c.Call.Return(run)
return _c
}
// Run provides a mock function with given fields: ctx
func (_m *MockClientServer) Run(ctx context.Context) error {
ret := _m.Called(ctx)
if len(ret) == 0 {
panic("no return value specified for Run")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
r0 = rf(ctx)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockClientServer_Run_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Run'
type MockClientServer_Run_Call struct {
*mock.Call
}
// Run is a helper method to define mock.On call
// - ctx context.Context
func (_e *MockClientServer_Expecter) Run(ctx interface{}) *MockClientServer_Run_Call {
return &MockClientServer_Run_Call{Call: _e.mock.On("Run", ctx)}
}
func (_c *MockClientServer_Run_Call) Run(run func(ctx context.Context)) *MockClientServer_Run_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context))
})
return _c
}
func (_c *MockClientServer_Run_Call) Return(err error) *MockClientServer_Run_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockClientServer_Run_Call) RunAndReturn(run func(context.Context) error) *MockClientServer_Run_Call {
_c.Call.Return(run)
return _c
}
// ServerStarted provides a mock function with given fields:
func (_m *MockClientServer) ServerStarted() bool {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for ServerStarted")
}
var r0 bool
if rf, ok := ret.Get(0).(func() bool); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockClientServer_ServerStarted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ServerStarted'
type MockClientServer_ServerStarted_Call struct {
*mock.Call
}
// ServerStarted is a helper method to define mock.On call
func (_e *MockClientServer_Expecter) ServerStarted() *MockClientServer_ServerStarted_Call {
return &MockClientServer_ServerStarted_Call{Call: _e.mock.On("ServerStarted")}
}
func (_c *MockClientServer_ServerStarted_Call) Run(run func()) *MockClientServer_ServerStarted_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockClientServer_ServerStarted_Call) Return(_a0 bool) *MockClientServer_ServerStarted_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockClientServer_ServerStarted_Call) RunAndReturn(run func() bool) *MockClientServer_ServerStarted_Call {
_c.Call.Return(run)
return _c
}
// NewMockClientServer creates a new instance of MockClientServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockClientServer(t interface {
mock.TestingT
Cleanup(func())
}) *MockClientServer {
mock := &MockClientServer{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View file

@ -13,6 +13,7 @@ import (
"github.com/anyproto/any-sync/accountservice"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/peerstatus"
"github.com/anyproto/any-sync/nodeconf"
"github.com/anyproto/any-sync/util/periodicsync"
"github.com/libp2p/zeroconf/v2"
@ -21,12 +22,17 @@ import (
"github.com/anyproto/anytype-heart/core/anytype/config"
"github.com/anyproto/anytype-heart/core/event"
"github.com/anyproto/anytype-heart/net/addrs"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/space/spacecore/clientserver"
)
var interfacesSortPriority = []string{"en", "wlan", "wl", "eth", "lo"}
type StatusUpdater interface {
BroadcastStatus(status peerstatus.Status)
SendPeerUpdate(spaceIds []string)
BroadcastPeerUpdate()
}
type localDiscovery struct {
server *zeroconf.Server
peerId string
@ -40,13 +46,14 @@ type localDiscovery struct {
drpcServer clientserver.ClientServer
nodeConf nodeconf.Configuration
ipv4 []string
ipv6 []string
manualStart bool
started bool
notifier Notifier
m sync.Mutex
eventSender event.Sender
ipv4 []string
ipv6 []string
manualStart bool
started bool
notifier Notifier
m sync.Mutex
eventSender event.Sender
peerToPeerStatusUpdater StatusUpdater
}
func New() LocalDiscovery {
@ -62,15 +69,15 @@ func (l *localDiscovery) Init(a *app.App) (err error) {
l.nodeConf = a.MustComponent(config.CName).(*config.Config).GetNodeConf()
l.peerId = a.MustComponent(accountservice.CName).(accountservice.Service).Account().PeerId
l.periodicCheck = periodicsync.NewPeriodicSync(30, 0, l.checkAddrs, log)
l.drpcServer = a.MustComponent(clientserver.CName).(clientserver.ClientServer)
l.drpcServer = app.MustComponent[clientserver.ClientServer](a)
l.eventSender = app.MustComponent[event.Sender](a)
l.peerToPeerStatusUpdater = app.MustComponent[StatusUpdater](a)
return
}
func (l *localDiscovery) Run(ctx context.Context) (err error) {
if l.manualStart && len(l.nodeConf.Nodes) > 0 {
// let's wait for the explicit command to enable local discovery
l.sendP2PStatusEvent(pb.EventP2PStatus_NotConnected)
return
}
@ -79,6 +86,7 @@ func (l *localDiscovery) Run(ctx context.Context) (err error) {
func (l *localDiscovery) Start() (err error) {
if !l.drpcServer.ServerStarted() {
l.peerToPeerStatusUpdater.BroadcastStatus(peerstatus.NotPossible)
return
}
l.m.Lock()
@ -136,6 +144,9 @@ func (l *localDiscovery) Close(ctx context.Context) (err error) {
func (l *localDiscovery) checkAddrs(ctx context.Context) (err error) {
newAddrs, err := addrs.GetInterfacesAddrs()
if len(newAddrs.Interfaces) == 0 {
l.peerToPeerStatusUpdater.BroadcastStatus(peerstatus.NotPossible)
}
if err != nil {
return
}
@ -199,6 +210,7 @@ func (l *localDiscovery) readAnswers(ch chan *zeroconf.ServiceEntry) {
for entry := range ch {
if entry.Instance == l.peerId {
log.Debug("discovered self")
l.peerToPeerStatusUpdater.BroadcastPeerUpdate()
continue
}
var portAddrs []string
@ -225,13 +237,10 @@ func (l *localDiscovery) browse(ctx context.Context, ch chan *zeroconf.ServiceEn
err error
newAddrs addrs.InterfacesAddrs
)
defer func() {
if err != nil {
l.sendP2PStatusEvent(pb.EventP2PStatus_NotConnected)
}
}()
l.sendP2PStatusEvent(pb.EventP2PStatus_Connected)
newAddrs, err = addrs.GetInterfacesAddrs()
if len(newAddrs.Interfaces) == 0 {
l.peerToPeerStatusUpdater.BroadcastStatus(peerstatus.NotPossible)
}
if err != nil {
return
}
@ -244,15 +253,3 @@ func (l *localDiscovery) browse(ctx context.Context, ch chan *zeroconf.ServiceEn
log.Error("browsing failed", zap.Error(err))
}
}
func (l *localDiscovery) sendP2PStatusEvent(status pb.EventP2PStatusStatus) {
l.eventSender.Broadcast(&pb.Event{Messages: []*pb.EventMessage{
{
Value: &pb.EventMessageValueOfP2PStatusUpdate{
P2PStatusUpdate: &pb.EventP2PStatusUpdate{
Status: status,
},
},
},
}})
}

View file

@ -8,6 +8,7 @@ import (
"github.com/anyproto/any-sync/accountservice"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/peerstatus"
"go.uber.org/zap"
"github.com/anyproto/anytype-heart/core/anytype/config"
@ -40,10 +41,11 @@ type localDiscovery struct {
peerId string
port int
notifier Notifier
drpcServer clientserver.ClientServer
manualStart bool
m sync.Mutex
peerToPeerStatusUpdater StatusUpdater
notifier Notifier
drpcServer clientserver.ClientServer
manualStart bool
m sync.Mutex
}
func (l *localDiscovery) PeerDiscovered(peer DiscoveredPeer, own OwnAddresses) {
@ -53,6 +55,9 @@ func (l *localDiscovery) PeerDiscovered(peer DiscoveredPeer, own OwnAddresses) {
}
// TODO: move this to android side
newAddrs, err := addrs.GetInterfacesAddrs()
if len(newAddrs.Interfaces) == 0 {
l.peerToPeerStatusUpdater.BroadcastStatus(peerstatus.NotPossible)
}
if err != nil {
return
}
@ -83,6 +88,7 @@ func (l *localDiscovery) Init(a *app.App) (err error) {
l.peerId = a.MustComponent(accountservice.CName).(accountservice.Service).Account().PeerId
l.drpcServer = a.MustComponent(clientserver.CName).(clientserver.ClientServer)
l.manualStart = a.MustComponent(config.CName).(*config.Config).DontStartLocalNetworkSyncAutomatically
l.peerToPeerStatusUpdater = app.MustComponent[StatusUpdater](a)
return
}

View file

@ -0,0 +1,101 @@
package localdiscovery
import (
"context"
"testing"
"github.com/anyproto/any-sync/accountservice/mock_accountservice"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/object/accountdata"
"github.com/anyproto/any-sync/nodeconf/mock_nodeconf"
"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"
"github.com/anyproto/anytype-heart/core/anytype/config"
"github.com/anyproto/anytype-heart/core/event/mock_event"
"github.com/anyproto/anytype-heart/core/syncstatus/p2p"
"github.com/anyproto/anytype-heart/space/spacecore/clientserver/mock_clientserver"
"github.com/anyproto/anytype-heart/tests/testutil"
)
type fixture struct {
LocalDiscovery
nodeConf *mock_nodeconf.MockService
eventSender *mock_event.MockSender
peerToPeerStatusUpdater *p2p.Observers
clientServer *mock_clientserver.MockClientServer
account *mock_accountservice.MockService
}
func newFixture(t *testing.T) *fixture {
ctrl := gomock.NewController(t)
c := &config.Config{}
nodeConf := mock_nodeconf.NewMockService(ctrl)
eventSender := mock_event.NewMockSender(t)
peerToPeerStatusUpdater := p2p.NewObservers()
clientServer := mock_clientserver.NewMockClientServer(t)
accountKeys, err := accountdata.NewRandom()
assert.Nil(t, err)
account := mock_accountservice.NewAccountServiceWithAccount(ctrl, accountKeys)
a := &app.App{}
ctx := context.Background()
a.Register(c).
Register(testutil.PrepareMock(ctx, a, nodeConf)).
Register(testutil.PrepareMock(ctx, a, eventSender)).
Register(peerToPeerStatusUpdater).
Register(account).
Register(testutil.PrepareMock(ctx, a, clientServer))
discovery := New()
err = discovery.Init(a)
assert.Nil(t, err)
f := &fixture{
LocalDiscovery: discovery,
nodeConf: nodeConf,
eventSender: eventSender,
peerToPeerStatusUpdater: peerToPeerStatusUpdater,
clientServer: clientServer,
account: account,
}
return f
}
func TestLocalDiscovery_Init(t *testing.T) {
t.Run("init success", func(t *testing.T) {
// given
f := newFixture(t)
// when
f.clientServer.EXPECT().ServerStarted().Return(true)
f.clientServer.EXPECT().Port().Return(6789)
err := f.Run(context.Background())
assert.Nil(t, err)
// then
err = f.Close(context.Background())
assert.Nil(t, err)
})
}
func TestLocalDiscovery_checkAddrs(t *testing.T) {
t.Run("checkAddrs - server run successfully", func(t *testing.T) {
// given
f := newFixture(t)
f.clientServer.EXPECT().ServerStarted().Return(true)
f.clientServer.EXPECT().Port().Return(6789)
err := f.Run(context.Background())
assert.Nil(t, err)
// when
ld := f.LocalDiscovery.(*localDiscovery)
err = ld.checkAddrs(context.Background())
// then
assert.Nil(t, err)
})
}

View file

@ -39,6 +39,7 @@ func (s *service) PeerDiscovered(peer localdiscovery.DiscoveredPeer, own localdi
}
log.Debug("got peer ids from peer", zap.String("peer", peer.PeerId), zap.Strings("spaces", resp.SpaceIds))
s.peerStore.UpdateLocalPeer(peer.PeerId, resp.SpaceIds)
s.peerToPeerStatus.SendPeerUpdate(resp.SpaceIds)
}
func (s *service) addSchema(addrs []string) (res []string) {

View file

@ -25,6 +25,10 @@ var (
ErrPeerFindDeadlineExceeded = errors.New("peer find deadline exceeded")
)
type StatusUpdater interface {
SendPeerUpdate(spaceIds []string)
}
type clientPeerManager struct {
spaceId string
responsibleNodeIds []string
@ -35,18 +39,20 @@ type clientPeerManager struct {
watchingPeers map[string]struct{}
rebuildResponsiblePeers chan struct{}
availableResponsiblePeers chan struct{}
peerToPeerStatusObserver StatusUpdater
ctx context.Context
ctxCancel context.CancelFunc
sync.Mutex
}
func (n *clientPeerManager) Init(_ *app.App) (err error) {
func (n *clientPeerManager) Init(a *app.App) (err error) {
n.responsibleNodeIds = n.peerStore.ResponsibleNodeIds(n.spaceId)
n.ctx, n.ctxCancel = context.WithCancel(context.Background())
n.rebuildResponsiblePeers = make(chan struct{}, 1)
n.watchingPeers = make(map[string]struct{})
n.availableResponsiblePeers = make(chan struct{})
n.peerToPeerStatusObserver = app.MustComponent[StatusUpdater](a)
return
}
@ -143,15 +149,20 @@ func (n *clientPeerManager) getStreamResponsiblePeers(ctx context.Context) (peer
peerIds = []string{p.Id()}
}
peerIds = append(peerIds, n.peerStore.LocalPeerIds(n.spaceId)...)
var needUpdate bool
for _, peerId := range peerIds {
p, err := n.p.pool.Get(ctx, peerId)
if err != nil {
n.peerStore.RemoveLocalPeer(peerId)
log.Warn("failed to get peer from stream pool", zap.String("peerId", peerId), zap.Error(err))
needUpdate = true
continue
}
peers = append(peers, p)
}
if needUpdate {
n.peerToPeerStatusObserver.SendPeerUpdate([]string{n.spaceId})
}
// set node error if no local peers
if len(peers) == 0 {
err = fmt.Errorf("failed to get peers for stream")
@ -181,15 +192,20 @@ func (n *clientPeerManager) fetchResponsiblePeers() {
}
peerIds := n.peerStore.LocalPeerIds(n.spaceId)
var needUpdate bool
for _, peerId := range peerIds {
p, err := n.p.pool.Get(n.ctx, peerId)
if err != nil {
n.peerStore.RemoveLocalPeer(peerId)
log.Warn("failed to get local from net pool", zap.String("peerId", peerId), zap.Error(err))
needUpdate = true
continue
}
peers = append(peers, p)
}
if needUpdate {
n.peerToPeerStatusObserver.SendPeerUpdate([]string{n.spaceId})
}
n.Lock()
defer n.Unlock()

View file

@ -9,8 +9,15 @@ import (
"time"
"github.com/anyproto/any-sync/net/peer"
"github.com/anyproto/any-sync/net/pool/mock_pool"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"storj.io/drpc"
"github.com/anyproto/anytype-heart/core/syncstatus/p2p"
"github.com/anyproto/anytype-heart/core/syncstatus/p2p/mock_p2p"
"github.com/anyproto/anytype-heart/space/spacecore/peerstore"
)
func TestClientPeerManager_GetResponsiblePeers_Deadline(t *testing.T) {
@ -79,6 +86,99 @@ func TestClientPeerManager_GetResponsiblePeers_Deadline(t *testing.T) {
})
}
func Test_fetchResponsiblePeers(t *testing.T) {
spaceId := "spaceId"
t.Run("no local peers", func(t *testing.T) {
// given
f := newFixtureManager(t, spaceId)
// when
f.pool.EXPECT().GetOneOf(gomock.Any(), gomock.Any()).Return(newTestPeer("id"), nil)
f.cm.fetchResponsiblePeers()
// then
f.p2pStatusSender.AssertNotCalled(t, "SendPeerUpdate")
})
t.Run("local peers connected", func(t *testing.T) {
// given
f := newFixtureManager(t, spaceId)
f.store.UpdateLocalPeer("peerId", []string{spaceId})
// when
f.pool.EXPECT().GetOneOf(gomock.Any(), gomock.Any()).Return(newTestPeer("id"), nil)
f.pool.EXPECT().Get(f.cm.ctx, "peerId").Return(newTestPeer("id1"), nil)
f.cm.fetchResponsiblePeers()
// then
f.p2pStatusSender.AssertNotCalled(t, "SendPeerUpdate")
})
t.Run("local peer not connected", func(t *testing.T) {
// given
f := newFixtureManager(t, spaceId)
f.store.UpdateLocalPeer("peerId", []string{spaceId})
// when
f.pool.EXPECT().GetOneOf(gomock.Any(), gomock.Any()).Return(newTestPeer("id"), nil)
f.pool.EXPECT().Get(f.cm.ctx, "peerId").Return(nil, fmt.Errorf("error"))
f.p2pStatusSender.EXPECT().SendPeerUpdate().Return()
f.cm.fetchResponsiblePeers()
// then
f.p2pStatusSender.AssertCalled(t, "SendPeerUpdate")
})
}
func Test_getStreamResponsiblePeers(t *testing.T) {
spaceId := "spaceId"
t.Run("no local peers", func(t *testing.T) {
// given
f := newFixtureManager(t, spaceId)
// when
f.pool.EXPECT().GetOneOf(gomock.Any(), gomock.Any()).Return(newTestPeer("id"), nil)
f.pool.EXPECT().Get(gomock.Any(), gomock.Any()).Return(newTestPeer("id"), nil)
peers, err := f.cm.getStreamResponsiblePeers(context.Background())
// then
assert.Nil(t, err)
assert.Len(t, peers, 1)
f.p2pStatusSender.AssertNotCalled(t, "SendPeerUpdate")
})
t.Run("local peers connected", func(t *testing.T) {
// given
f := newFixtureManager(t, spaceId)
f.store.UpdateLocalPeer("peerId", []string{spaceId})
// when
f.pool.EXPECT().GetOneOf(gomock.Any(), gomock.Any()).Return(newTestPeer("id"), nil)
f.pool.EXPECT().Get(f.cm.ctx, "peerId").Return(newTestPeer("id1"), nil)
f.pool.EXPECT().Get(f.cm.ctx, "id").Return(newTestPeer("id"), nil)
peers, err := f.cm.getStreamResponsiblePeers(context.Background())
// then
assert.Nil(t, err)
assert.Len(t, peers, 2)
f.p2pStatusSender.AssertNotCalled(t, "SendPeerUpdate")
})
t.Run("local peer not connected", func(t *testing.T) {
// given
f := newFixtureManager(t, spaceId)
f.store.UpdateLocalPeer("peerId", []string{spaceId})
// when
f.pool.EXPECT().GetOneOf(gomock.Any(), gomock.Any()).Return(newTestPeer("id"), nil)
f.pool.EXPECT().Get(f.cm.ctx, "peerId").Return(nil, fmt.Errorf("error"))
f.pool.EXPECT().Get(f.cm.ctx, "id").Return(newTestPeer("id"), nil)
f.p2pStatusSender.EXPECT().SendPeerUpdate().Return()
peers, err := f.cm.getStreamResponsiblePeers(context.Background())
// then
assert.Nil(t, err)
assert.Len(t, peers, 1)
f.p2pStatusSender.AssertCalled(t, "SendPeerUpdate")
})
}
func newTestPeer(id string) *testPeer {
return &testPeer{
id: id,
@ -154,3 +254,34 @@ func (t *testPeer) IsClosed() bool {
func (t *testPeer) CloseChan() <-chan struct{} {
return t.closed
}
type fixture struct {
cm *clientPeerManager
pool *mock_pool.MockPool
p2pStatusSender *mock_p2p.MockStatusUpdateSender
store peerstore.PeerStore
}
func newFixtureManager(t *testing.T, spaceId string) *fixture {
ctrl := gomock.NewController(t)
pool := mock_pool.NewMockPool(ctrl)
provider := &provider{pool: pool}
store := peerstore.New()
observers := p2p.NewObservers()
p2pStatusSender := mock_p2p.NewMockStatusUpdateSender(t)
observers.AddObserver(spaceId, p2pStatusSender)
cm := &clientPeerManager{
p: provider,
spaceId: spaceId,
peerStore: store,
peerToPeerStatusObserver: observers,
watchingPeers: map[string]struct{}{},
ctx: context.Background(),
}
return &fixture{
cm: cm,
pool: pool,
p2pStatusSender: p2pStatusSender,
store: store,
}
}

View file

@ -27,7 +27,6 @@ type PeerStore interface {
func New() PeerStore {
return &peerStore{
localPeerIdsBySpace: map[string][]string{},
responsibleIds: map[string][]string{},
spacesByLocalPeerIds: map[string][]string{},
Mutex: sync.Mutex{},
}
@ -40,7 +39,6 @@ type peerStore struct {
localPeerIds []string
localPeerIdsBySpace map[string][]string
spacesByLocalPeerIds map[string][]string
responsibleIds map[string][]string
observers []Observer
sync.Mutex
}

View file

@ -30,6 +30,7 @@ import (
"github.com/anyproto/anytype-heart/core/anytype/config"
"github.com/anyproto/anytype-heart/core/block/object/treesyncer"
"github.com/anyproto/anytype-heart/core/syncstatus/p2p"
"github.com/anyproto/anytype-heart/core/wallet"
"github.com/anyproto/anytype-heart/space/spacecore/clientspaceproto"
"github.com/anyproto/anytype-heart/space/spacecore/localdiscovery"
@ -50,6 +51,10 @@ func New() SpaceCoreService {
return &service{}
}
type StatusUpdater interface {
SendPeerUpdate(spaceIds []string)
}
type PoolManager interface {
UnaryPeerPool() pool.Pool
StreamPeerPool() pool.Pool
@ -83,6 +88,7 @@ type service struct {
poolManager PoolManager
streamHandler *streamHandler
syncStatusService syncStatusService
peerToPeerStatus StatusUpdater
}
type syncStatusService interface {
@ -119,6 +125,7 @@ func (s *service) Init(a *app.App) (err error) {
ocache.WithTTL(time.Duration(s.conf.GCTTL)*time.Second),
)
s.peerToPeerStatus = app.MustComponent[StatusUpdater](a)
err = spacesyncproto.DRPCRegisterSpaceSync(a.MustComponent(server.CName).(server.DRPCServer), &rpcHandler{s})
if err != nil {
return
@ -244,7 +251,7 @@ func (s *service) Delete(ctx context.Context, spaceID string) (err error) {
}
func (s *service) loadSpace(ctx context.Context, id string) (value ocache.Object, err error) {
cc, err := s.commonSpace.NewSpace(ctx, id, commonspace.Deps{TreeSyncer: treesyncer.NewTreeSyncer(id)})
cc, err := s.commonSpace.NewSpace(ctx, id, commonspace.Deps{TreeSyncer: treesyncer.NewTreeSyncer(id), PeerStatus: p2p.NewP2PStatus(id)})
if err != nil {
return
}

View file

@ -5,6 +5,7 @@
//
// mockgen -package mockSource -destination source_mock.go github.com/anyproto/anytype-heart/core/block/source Service,Source
//
// Package mockSource is a generated GoMock package.
package mockSource