From ec63ba2de4d85605764e04dec3db91690bd6db59 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Mon, 28 Jun 2021 16:54:11 -0700 Subject: [PATCH 1/2] Update 'README.md' --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c374a14..a4f7806 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,9 @@ Development and Contributing information in [CONTRIBUTING.md](https://git.openpr ## Running Cwtch ### Server #### Docker + +### NOTE: The following section is out of date. The new Cwtch server is available from https://git.openprivacy.ca/cwtch.im/server, but there is no current docker container for it. + This repository contains a `Dockerfile` allowing you to build and run the server as a [docker](https://www.docker.com/) container. To get started issue `docker build -t openpriv/cwtch-server:latest .`, this will create 2 temporary docker containers, one to build the Tor daemon and one to build Cwtch. The compiled binaries will then be bundled into a new image and tagged as `openpriv/cwtch-server:latest`. From f4caddbc1b4181ffc6f256e92cd6c8e9ec735b56 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Wed, 1 Sep 2021 15:20:03 -0700 Subject: [PATCH 2/2] File Sharing MVP --- event/common.go | 27 +- .../filesharing/filesharing_functionality.go | 87 +++++ model/overlay.go | 19 ++ peer/cwtch_peer.go | 45 ++- protocol/connections/engine.go | 60 +++- protocol/connections/peerapp.go | 14 +- protocol/files/chunkspec.go | 87 +++++ protocol/files/chunkspec_test.go | 37 +++ protocol/files/filesharing_subsystem.go | 201 +++++++++++ protocol/files/manifest.go | 312 ++++++++++++++++++ protocol/files/manifest_test.go | 128 +++++++ protocol/files/testdata/cwtch.out.png | Bin 0 -> 51791 bytes protocol/files/testdata/cwtch.png | Bin 0 -> 51791 bytes protocol/files/testdata/cwtch.png.manifest | 1 + protocol/files/testdata/example.txt | 1 + protocol/model/peermessage.go.go | 8 + testing/cwtch.png | Bin 0 -> 51791 bytes testing/file_sharing_integration_test.go | 132 ++++++++ testing/tests.sh | 1 + 19 files changed, 1141 insertions(+), 19 deletions(-) create mode 100644 functionality/filesharing/filesharing_functionality.go create mode 100644 model/overlay.go create mode 100644 protocol/files/chunkspec.go create mode 100644 protocol/files/chunkspec_test.go create mode 100644 protocol/files/filesharing_subsystem.go create mode 100644 protocol/files/manifest.go create mode 100644 protocol/files/manifest_test.go create mode 100644 protocol/files/testdata/cwtch.out.png create mode 100644 protocol/files/testdata/cwtch.png create mode 100644 protocol/files/testdata/cwtch.png.manifest create mode 100644 protocol/files/testdata/example.txt create mode 100644 protocol/model/peermessage.go.go create mode 100644 testing/cwtch.png create mode 100644 testing/file_sharing_integration_test.go diff --git a/event/common.go b/event/common.go index f5a7332..e2deea6 100644 --- a/event/common.go +++ b/event/common.go @@ -248,6 +248,14 @@ const ( // For situations where we want to update $Identity -> $RemotePeer/$GroupID's total message count to be $Data MessageCounterResync = Type("MessageCounterResync") + + // File Handling Events + ShareManifest = Type("ShareManifest") + ManifestSizeReceived = Type("ManifestSizeReceived") + ManifestReceived = Type("ManifestReceived") + ManifestSaved = Type("ManifestSaved") + FileDownloadProgressUpdate = Type("FileDownloadProgressUpdate") + FileDownloaded = Type("FileDownloaded") ) // Field defines common event attributes @@ -312,6 +320,11 @@ const ( Imported = Field("Imported") Source = Field("Source") + + FileKey = Field("FileKey") + FileSizeInChunks = Field("FileSizeInChunks") + ManifestSize = Field("ManifestSize") + SerializedManifest = Field("SerializedManifest") ) // Defining Common errors @@ -328,11 +341,15 @@ const ( // Defining Protocol Contexts const ( - ContextAck = "im.cwtch.acknowledgement" - ContextInvite = "im.cwtch.invite" - ContextRaw = "im.cwtch.raw" - ContextGetVal = "im.cwtch.getVal" - ContextRetVal = "im.cwtch.retVal" + ContextAck = "im.cwtch.acknowledgement" + ContextInvite = "im.cwtch.invite" + ContextRaw = "im.cwtch.raw" + ContextGetVal = "im.cwtch.getVal" + ContextRetVal = "im.cwtch.retVal" + ContextRequestManifest = "im.cwtch.file.request.manifest" + ContextSendManifest = "im.cwtch.file.send.manifest" + ContextRequestFile = "im.cwtch.file.request.chunk" + ContextSendFile = "im.cwtch.file.send.chunk" ) // Define Default Attribute Keys diff --git a/functionality/filesharing/filesharing_functionality.go b/functionality/filesharing/filesharing_functionality.go new file mode 100644 index 0000000..fe5c3cf --- /dev/null +++ b/functionality/filesharing/filesharing_functionality.go @@ -0,0 +1,87 @@ +package filesharing + +import ( + "crypto/rand" + "cwtch.im/cwtch/model" + "cwtch.im/cwtch/model/attr" + "cwtch.im/cwtch/peer" + "cwtch.im/cwtch/protocol/files" + "encoding/json" + "errors" + "fmt" + "git.openprivacy.ca/openprivacy/log" + "io" + "math" + "path" + "strconv" +) + +// Functionality groups some common UI triggered functions for contacts... +type Functionality struct { +} + +// FunctionalityGate returns contact.Functionality always +func FunctionalityGate(experimentMap map[string]bool) (*Functionality, error) { + if experimentMap["filesharing"] == true { + return new(Functionality), nil + } + return nil, errors.New("filesharing is not enabled") +} + +// OverlayMessage presents the canonical format of the File Sharing functionality Overlay Message +// This is the format that the UI will parse to display the message +type OverlayMessage struct { + Name string `json:"f"` + Hash []byte `json:"h"` + Nonce []byte `json:"n"` + Size uint64 `json:"s"` +} + +// DownloadFile given a profile, a conversation handle and a file sharing key, start off a download process +// to downloadFilePath +func (f *Functionality) DownloadFile(profile peer.CwtchPeer, handle string, downloadFilePath string, key string) { + profile.SetAttribute(attr.GetLocalScope(key), downloadFilePath) + profile.SendGetValToPeer(handle, attr.PublicScope, fmt.Sprintf("%s.manifest.size", key)) +} + +// ShareFile given a profile and a conversation handle, sets up a file sharing process to share the file +// at filepath +func (f *Functionality) ShareFile(filepath string, profile peer.CwtchPeer, handle string) error { + manifest, err := files.CreateManifest(filepath) + if err != nil { + return err + } + + var nonce [24]byte + if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil { + log.Errorf("Cannot read from random: %v\n", err) + return err + } + + message := OverlayMessage{ + Name: path.Base(manifest.FileName), + Hash: manifest.RootHash, + Nonce: nonce[:], + Size: manifest.FileSizeInBytes, + } + + data, _ := json.Marshal(message) + + wrapper := model.MessageWrapper{ + Overlay: model.OverlayFileSharing, + Data: string(data), + } + + wrapperJSON, _ := json.Marshal(wrapper) + key := fmt.Sprintf("%x.%x", manifest.RootHash, nonce) + serializedManifest, _ := json.Marshal(manifest) + profile.ShareFile(key, string(serializedManifest)) + + // Store the size of the manifest (in chunks) as part of the public scope so contacts who we share the file with + // can fetch the manifest as if it were a file. + profile.SetAttribute(attr.GetPublicScope(fmt.Sprintf("%s.manifest.size", key)), strconv.Itoa(int(math.Ceil(float64(len(serializedManifest))/float64(files.DefaultChunkSize))))) + + profile.SendMessageToPeer(handle, string(wrapperJSON)) + + return nil +} diff --git a/model/overlay.go b/model/overlay.go new file mode 100644 index 0000000..4149798 --- /dev/null +++ b/model/overlay.go @@ -0,0 +1,19 @@ +package model + +// MessageWrapper is the canonical Cwtch overlay wrapper +type MessageWrapper struct { + Overlay int `json:"o"` + Data string `json:"d"` +} + +// OverlayChat is the canonical identifier for chat overlays +const OverlayChat = 1 + +// OverlayInviteContact is the canonical identifier for the contact invite overlay +const OverlayInviteContact = 100 + +// OverlayInviteGroup is the canonical identifier for the group invite overlay +const OverlayInviteGroup = 101 + +// OverlayFileSharing is the canonical identifier for the file sharing overlay +const OverlayFileSharing = 200 diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index a4867e4..7dd385f 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -5,10 +5,12 @@ import ( "cwtch.im/cwtch/model" "cwtch.im/cwtch/model/attr" "cwtch.im/cwtch/protocol/connections" + "cwtch.im/cwtch/protocol/files" "encoding/base32" "encoding/base64" "encoding/json" "errors" + "fmt" "git.openprivacy.ca/openprivacy/log" "strconv" "strings" @@ -21,7 +23,8 @@ const lastKnownSignature = "LastKnowSignature" var autoHandleableEvents = map[event.Type]bool{event.EncryptedGroupMessage: true, event.PeerStateChange: true, event.ServerStateChange: true, event.NewGroupInvite: true, event.NewMessageFromPeer: true, event.PeerAcknowledgement: true, event.PeerError: true, event.SendMessageToPeerError: true, event.SendMessageToGroupError: true, - event.NewGetValMessageFromPeer: true, event.NewRetValMessageFromPeer: true, event.ProtocolEngineStopped: true, event.RetryServerRequest: true} + event.NewGetValMessageFromPeer: true, event.NewRetValMessageFromPeer: true, event.ProtocolEngineStopped: true, event.RetryServerRequest: true, + event.ManifestSizeReceived: true, event.ManifestReceived: true} // DefaultEventsToHandle specifies which events will be subscribed to // when a peer has its Init() function called @@ -189,6 +192,8 @@ type CwtchPeer interface { SendMessages ModifyMessages SendMessagesToGroup + + ShareFile(fileKey string, serializedManifest string) } // NewCwtchPeer creates and returns a new cwtchPeer with the given name. @@ -702,6 +707,10 @@ func (cp *cwtchPeer) StoreMessage(onion string, messageTxt string, sent time.Tim cp.mutex.Unlock() } +func (cp *cwtchPeer) ShareFile(fileKey string, serializedManifest string) { + cp.eventBus.Publish(event.NewEvent(event.ShareManifest, map[event.Field]string{event.FileKey: fileKey, event.SerializedManifest: serializedManifest})) +} + // eventHandler process events from other subsystems func (cp *cwtchPeer) eventHandler() { for { @@ -795,6 +804,33 @@ func (cp *cwtchPeer) eventHandler() { /***** Non default but requestable handlable events *****/ + case event.ManifestReceived: + log.Debugf("Manifest Received Event!: %v", ev) + handle := ev.Data[event.Handle] + fileKey := ev.Data[event.FileKey] + serializedManifest := ev.Data[event.SerializedManifest] + + downloadFilePath, exists := cp.GetAttribute(attr.GetLocalScope(fileKey)) + if exists { + log.Debugf("downloading file to %v", downloadFilePath) + var manifest files.Manifest + err := json.Unmarshal([]byte(serializedManifest), &manifest) + if err == nil { + manifest.FileName = downloadFilePath + log.Debugf("saving manifest") + err = manifest.Save(fmt.Sprintf("%v.manifest", downloadFilePath)) + if err != nil { + log.Errorf("could not save manifest...") + } else { + cp.eventBus.Publish(event.NewEvent(event.ManifestSaved, map[event.Field]string{event.FileKey: fileKey, event.Handle: handle, event.SerializedManifest: string(manifest.Serialize())})) + } + } else { + log.Errorf("error saving manifest: %v", err) + } + } else { + log.Errorf("no download path found for manifest: %v", fileKey) + } + case event.NewRetValMessageFromPeer: onion := ev.Data[event.RemotePeer] scope := ev.Data[event.Scope] @@ -804,7 +840,12 @@ func (cp *cwtchPeer) eventHandler() { log.Debugf("NewRetValMessageFromPeer %v %v%v %v %v\n", onion, scope, path, exists, val) if exists { if scope == attr.PublicScope { - cp.SetContactAttribute(onion, attr.GetPeerScope(path), val) + if strings.HasSuffix(path, ".manifest.size") { + fileKey := strings.Replace(path, ".manifest.size", "", 1) + cp.eventBus.Publish(event.NewEvent(event.ManifestSizeReceived, map[event.Field]string{event.FileKey: fileKey, event.ManifestSize: val, event.Handle: onion})) + } else { + cp.SetContactAttribute(onion, attr.GetPeerScope(path), val) + } } } case event.PeerStateChange: diff --git a/protocol/connections/engine.go b/protocol/connections/engine.go index 9d26f79..bfde30a 100644 --- a/protocol/connections/engine.go +++ b/protocol/connections/engine.go @@ -3,7 +3,9 @@ package connections import ( "cwtch.im/cwtch/event" "cwtch.im/cwtch/model" + "cwtch.im/cwtch/protocol/files" "cwtch.im/cwtch/protocol/groups" + model3 "cwtch.im/cwtch/protocol/model" "encoding/base64" "encoding/json" "errors" @@ -46,6 +48,9 @@ type engine struct { // Required for listen(), inaccessible from identity privateKey ed25519.PrivateKey + // file sharing subsystem is responsible for maintaining active shares and downloads + filesharingSubSystem files.FileSharingSubSystem + shuttingDown bool } @@ -92,6 +97,11 @@ func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateK engine.eventManager.Subscribe(event.BlockUnknownPeers, engine.queue) engine.eventManager.Subscribe(event.AllowUnknownPeers, engine.queue) + // File Handling + engine.eventManager.Subscribe(event.ShareManifest, engine.queue) + engine.eventManager.Subscribe(event.ManifestSizeReceived, engine.queue) + engine.eventManager.Subscribe(event.ManifestSaved, engine.queue) + for peer, authorization := range peerAuthorizations { engine.authorizations.Store(peer, authorization) } @@ -181,6 +191,20 @@ func (e *engine) eventHandler() { e.blockUnknownContacts = true case event.ProtocolEngineStartListen: go e.listenFn() + case event.ShareManifest: + e.filesharingSubSystem.ShareFile(ev.Data[event.FileKey], ev.Data[event.SerializedManifest]) + case event.ManifestSizeReceived: + handle := ev.Data[event.Handle] + key := ev.Data[event.FileKey] + size, _ := strconv.Atoi(ev.Data[event.ManifestSize]) + go e.sendPeerMessage(handle, e.filesharingSubSystem.FetchManifest(key, uint64(size))) + case event.ManifestSaved: + handle := ev.Data[event.Handle] + key := ev.Data[event.FileKey] + serializedManifest := ev.Data[event.SerializedManifest] + for _, message := range e.filesharingSubSystem.CompileChunkRequests(key, serializedManifest) { + go e.sendPeerMessage(handle, message) + } default: return } @@ -410,7 +434,7 @@ func (e *engine) sendMessageToPeer(eventID string, onion string, context string, if err == nil { peerApp, ok := (conn.App()).(*PeerApp) if ok { - peerApp.SendMessage(PeerMessage{eventID, context, message}) + peerApp.SendMessage(model3.PeerMessage{ID: eventID, Context: context, Data: message}) return nil } return errors.New("failed type assertion conn.App != PeerApp") @@ -419,7 +443,7 @@ func (e *engine) sendMessageToPeer(eventID string, onion string, context string, } func (e *engine) sendGetValToPeer(eventID, onion, scope, path string) error { - log.Debugf("sendGetValMessage to peer %v %v%v\n", onion, scope, path) + log.Debugf("sendGetValMessage to peer %v %v.%v\n", onion, scope, path) getVal := peerGetVal{Scope: scope, Path: path} message, err := json.Marshal(getVal) if err != nil { @@ -499,6 +523,28 @@ func (e *engine) handlePeerMessage(hostname string, eventID string, context stri ev.EventID = eventID e.eventManager.Publish(ev) } + } else if context == event.ContextRequestManifest { + for _, message := range e.filesharingSubSystem.RequestManifestParts(eventID) { + e.sendPeerMessage(hostname, message) + } + } else if context == event.ContextSendManifest { + if fileKey, manifest := e.filesharingSubSystem.ReceiveManifestPart(eventID, message); len(manifest) != 0 { + // We have a valid manifest + e.eventManager.Publish(event.NewEvent(event.ManifestReceived, map[event.Field]string{event.Handle: hostname, event.FileKey: fileKey, event.SerializedManifest: manifest})) + } + } else if context == event.ContextRequestFile { + for _, message := range e.filesharingSubSystem.ProcessChunkRequest(eventID, message) { + e.sendPeerMessage(hostname, message) + } + } else if context == event.ContextSendFile { + fileKey, downloaded, progress, totalChunks, _ := e.filesharingSubSystem.ProcessChunk(eventID, message) + if len(fileKey) != 0 { + if downloaded { + log.Debugf("file verified and downloaded!") + e.eventManager.Publish(event.NewEvent(event.FileDownloaded, map[event.Field]string{event.FileKey: fileKey})) + } + e.eventManager.Publish(event.NewEvent(event.FileDownloadProgressUpdate, map[event.Field]string{event.FileKey: fileKey, event.Progress: strconv.Itoa(int(progress)), event.FileSizeInChunks: strconv.Itoa(int(totalChunks))})) + } } else { e.eventManager.Publish(event.NewEvent(event.NewMessageFromPeer, map[event.Field]string{event.TimestampReceived: time.Now().Format(time.RFC3339Nano), event.RemotePeer: hostname, event.Data: string(message)})) } @@ -530,3 +576,13 @@ func (e *engine) leaveServer(server string) { e.ephemeralServices.Delete(server) } } + +func (e *engine) sendPeerMessage(handle string, message model3.PeerMessage) { + conn, err := e.service.WaitForCapabilityOrClose(handle, cwtchCapability) + if err == nil { + peerApp, ok := (conn.App()).(*PeerApp) + if ok { + peerApp.SendMessage(message) + } + } +} diff --git a/protocol/connections/peerapp.go b/protocol/connections/peerapp.go index a93179c..d97a7bf 100644 --- a/protocol/connections/peerapp.go +++ b/protocol/connections/peerapp.go @@ -2,6 +2,7 @@ package connections import ( "cwtch.im/cwtch/event" + model2 "cwtch.im/cwtch/protocol/model" "encoding/json" "git.openprivacy.ca/cwtch.im/tapir" "git.openprivacy.ca/cwtch.im/tapir/applications" @@ -27,13 +28,6 @@ type PeerApp struct { getValRequests sync.Map // [string]string eventID:Data } -// PeerMessage is an encapsulation that can be used by higher level applications -type PeerMessage struct { - ID string // A unique Message ID (primarily used for acknowledgments) - Context string // A unique context identifier i.e. im.cwtch.chat - Data []byte // The serialized data packet. -} - type peerGetVal struct { Scope, Path string } @@ -88,7 +82,7 @@ func (pa *PeerApp) listen() { pa.OnClose(pa.connection.Hostname()) return } - var peerMessage PeerMessage + var peerMessage model2.PeerMessage err := json.Unmarshal(message, &peerMessage) if err == nil { switch peerMessage.Context { @@ -106,7 +100,7 @@ func (pa *PeerApp) listen() { pa.MessageHandler(pa.connection.Hostname(), peerMessage.ID, peerMessage.Context, peerMessage.Data) // Acknowledge the message - pa.SendMessage(PeerMessage{peerMessage.ID, event.ContextAck, []byte{}}) + pa.SendMessage(model2.PeerMessage{ID: peerMessage.ID, Context: event.ContextAck, Data: []byte{}}) } } } else { @@ -117,7 +111,7 @@ func (pa *PeerApp) listen() { // SendMessage sends the peer a preformatted message // NOTE: This is a stub, we will likely want to extend this to better reflect the desired protocol -func (pa *PeerApp) SendMessage(message PeerMessage) { +func (pa *PeerApp) SendMessage(message model2.PeerMessage) { if message.Context == event.ContextGetVal { pa.getValRequests.Store(message.ID, string(message.Data)) } diff --git a/protocol/files/chunkspec.go b/protocol/files/chunkspec.go new file mode 100644 index 0000000..49725b3 --- /dev/null +++ b/protocol/files/chunkspec.go @@ -0,0 +1,87 @@ +package files + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +// ChunkSpec is a wrapper around an uncompressed array of chunk identifiers +type ChunkSpec []uint64 + +// CreateChunkSpec given a full list of chunks with their downloaded status (true for downloaded, false otherwise) +// derives a list of identifiers of chunks that have not been downloaded yet +func CreateChunkSpec(progress []bool) ChunkSpec { + var chunks ChunkSpec + for i, p := range progress { + if !p { + chunks = append(chunks, uint64(i)) + } + } + return chunks +} + +// Deserialize takes in a compressed chunk spec and returns an uncompressed ChunkSpec or an error +// if the serialized chunk spec has format errors +func Deserialize(serialized string) (*ChunkSpec, error) { + + var chunkSpec ChunkSpec + + if len(serialized) == 0 { + return &chunkSpec, nil + } + + ranges := strings.Split(serialized, ",") + for _, r := range ranges { + parts := strings.Split(r, ":") + if len(parts) == 1 { + single, err := strconv.Atoi(r) + if err != nil { + return nil, errors.New("invalid chunk spec") + } + chunkSpec = append(chunkSpec, uint64(single)) + } else if len(parts) == 2 { + start, err1 := strconv.Atoi(parts[0]) + end, err2 := strconv.Atoi(parts[1]) + if err1 != nil || err2 != nil { + return nil, errors.New("invalid chunk spec") + } + for i := start; i <= end; i++ { + chunkSpec = append(chunkSpec, uint64(i)) + } + } else { + return nil, errors.New("invalid chunk spec") + } + } + return &chunkSpec, nil +} + +// Serialize compresses the ChunkSpec into a list of inclusive ranges e.g. 1,2,3,5,6,7 becomes "1:3,5:7" +func (cs ChunkSpec) Serialize() string { + result := "" + + i := 0 + + for { + if i >= len(cs) { + break + } + j := i + 1 + for ; j < len(cs) && cs[j] == cs[j-1]+1; j++ { + } + + if result != "" { + result += "," + } + + if j == i+1 { + result += fmt.Sprintf("%d", cs[i]) + } else { + result += fmt.Sprintf("%d:%d", cs[i], cs[j-1]) + } + i = j + } + + return result +} diff --git a/protocol/files/chunkspec_test.go b/protocol/files/chunkspec_test.go new file mode 100644 index 0000000..990e78f --- /dev/null +++ b/protocol/files/chunkspec_test.go @@ -0,0 +1,37 @@ +package files + +import "testing" + +func TestChunkSpec(t *testing.T) { + + var testCases = map[string]ChunkSpec{ + "0": CreateChunkSpec([]bool{false}), + "0:10": CreateChunkSpec([]bool{false, false, false, false, false, false, false, false, false, false, false}), + "0:1,3:5,7:9": CreateChunkSpec([]bool{false, false, true, false, false, false, true, false, false, false, true}), + "": CreateChunkSpec([]bool{true, true, true, true, true, true, true, true, true, true, true}), + "2,5,8,10": CreateChunkSpec([]bool{true, true, false, true, true, false, true, true, false, true, false}), + // + "0,2:10": CreateChunkSpec([]bool{false, true, false, false, false, false, false, false, false, false, false}), + "0:8,10": CreateChunkSpec([]bool{false, false, false, false, false, false, false, false, false, true, false}), + "1:9": CreateChunkSpec([]bool{true, false, false, false, false, false, false, false, false, false, true}), + } + + for k, v := range testCases { + if k != v.Serialize() { + t.Fatalf("got %v but expected %v", v.Serialize(), k) + } + t.Logf("%v == %v", k, v.Serialize()) + } + + for k, v := range testCases { + if cs, err := Deserialize(k); err != nil { + t.Fatalf("error deserialized key: %v %v", k, err) + } else { + if v.Serialize() != cs.Serialize() { + t.Fatalf("got %v but expected %v", v.Serialize(), cs.Serialize()) + } + t.Logf("%v == %v", cs.Serialize(), v.Serialize()) + } + } + +} diff --git a/protocol/files/filesharing_subsystem.go b/protocol/files/filesharing_subsystem.go new file mode 100644 index 0000000..e900fdd --- /dev/null +++ b/protocol/files/filesharing_subsystem.go @@ -0,0 +1,201 @@ +package files + +import ( + "cwtch.im/cwtch/event" + "cwtch.im/cwtch/protocol/model" + "encoding/hex" + "encoding/json" + "fmt" + "git.openprivacy.ca/openprivacy/log" + "strconv" + "strings" + "sync" +) + +// FileSharingSubSystem encapsulates the functionality necessary to share and download files via Cwtch +// +type FileSharingSubSystem struct { + + // for sharing files + activeShares sync.Map // file key to manifest + + // for downloading files + prospectiveManifests sync.Map // file key to serialized manifests + activeDownloads sync.Map // file key to manifests +} + + +// ShareFile given a file key and a serialized manifest, allow the serialized manifest to be downloaded +// by Cwtch profiles in possession of the fileKey +func (fsss *FileSharingSubSystem) ShareFile(fileKey string, serializedManifest string) { + var manifest Manifest + err := json.Unmarshal([]byte(serializedManifest), &manifest) + if err != nil { + log.Errorf("could not share file %v", err) + return + } + fsss.activeShares.Store(fileKey, &manifest) +} + +// FetchManifest given a file key and knowledge of the manifest size in chunks (obtained via an attribute lookup) +// construct a request to download the manifest. +func (fsss *FileSharingSubSystem) FetchManifest(fileKey string, manifestSize uint64) model.PeerMessage { + fsss.prospectiveManifests.Store(fileKey, strings.Repeat("\"", int(manifestSize*DefaultChunkSize))) + return model.PeerMessage{ + Context: event.ContextRequestManifest, + ID: fileKey, + Data: []byte{}, + } +} + +// CompileChunkRequests takes in a complete serializedManifest and returns a set of chunk request messages +// TODO in the future we will want this to return the handles of contacts to request chunks from +func (fsss *FileSharingSubSystem) CompileChunkRequests(fileKey string, serializedManifest string) []model.PeerMessage { + var manifest Manifest + err := json.Unmarshal([]byte(serializedManifest), &manifest) + var messages []model.PeerMessage + if err == nil { + err := manifest.PrepareDownload() + if err == nil { + fsss.activeDownloads.Store(fileKey, &manifest) + log.Debugf("downloading file chunks: %v", manifest.GetChunkRequest().Serialize()) + messages = append(messages, model.PeerMessage{ + ID: fileKey, + Context: event.ContextRequestFile, + Data: []byte(manifest.GetChunkRequest().Serialize()), + }) + } + } + return messages +} + +// RequestManifestParts given a fileKey construct a set of messages representing requests to download various +// parts of the Manifest +func (fsss *FileSharingSubSystem) RequestManifestParts(fileKey string) []model.PeerMessage { + manifestI, exists := fsss.activeShares.Load(fileKey) + var messages []model.PeerMessage + if exists { + manifest := manifestI.(*Manifest) + serializedManifest := manifest.Serialize() + log.Debugf("found serialized manifest: %s", serializedManifest) + for i := 0; i < len(serializedManifest); i += DefaultChunkSize { + offset := i * DefaultChunkSize + end := (i + 1) * DefaultChunkSize + if end > len(serializedManifest) { + end = len(serializedManifest) + } + chunk := serializedManifest[offset:end] + messages = append(messages, model.PeerMessage{ + Context: event.ContextSendManifest, + ID: fmt.Sprintf("%s.%d", fileKey, uint64(i)), + Data: chunk, + }) + } + } + return messages +} + +// ReceiveManifestPart given a manifestKey reconstruct part the manifest from the provided part +func (fsss *FileSharingSubSystem) ReceiveManifestPart(manifestKey string, part []byte) (fileKey string, serializedManifest string) { + fileKeyParts := strings.Split(manifestKey, ".") + if len(fileKeyParts) == 3 { + fileKey = fmt.Sprintf("%s.%s", fileKeyParts[0], fileKeyParts[1]) + log.Debugf("manifest filekey: %s", fileKey) + manifestPart, err := strconv.Atoi(fileKeyParts[2]) + if err == nil { + serializedManifest, exists := fsss.prospectiveManifests.Load(fileKey) + if exists { + serializedManifest := serializedManifest.(string) + log.Debugf("loaded manifest") + offset := manifestPart * DefaultChunkSize + end := (manifestPart + 1) * DefaultChunkSize + + log.Debugf("storing manifest part %v %v", offset, end) + serializedManifestBytes := []byte(serializedManifest) + copy(serializedManifestBytes[offset:end], part[:]) + + if len(part) < DefaultChunkSize { + serializedManifestBytes = serializedManifestBytes[0 : len(serializedManifestBytes)-(DefaultChunkSize-len(part))] + } + + serializedManifest = string(serializedManifestBytes) + fsss.prospectiveManifests.Store(fileKey, serializedManifest) + log.Debugf("current manifest: [%s]", serializedManifest) + var manifest Manifest + err := json.Unmarshal([]byte(serializedManifest), &manifest) + if err == nil && hex.EncodeToString(manifest.RootHash) == fileKeyParts[0] { + log.Debugf("valid manifest received! %x", manifest.RootHash) + return fileKey, serializedManifest + } + } + } + } + return "", "" +} + +// ProcessChunkRequest given a fileKey, and a chunk request, compile a set of responses for each requested Chunk +func (fsss *FileSharingSubSystem) ProcessChunkRequest(fileKey string, serializedChunkRequest []byte) []model.PeerMessage { + log.Debugf("chunk request: %v", fileKey) + manifestI, exists := fsss.activeShares.Load(fileKey) + var messages []model.PeerMessage + if exists { + manifest := manifestI.(*Manifest) + log.Debugf("manifest found: %x", manifest.RootHash) + chunkSpec, err := Deserialize(string(serializedChunkRequest)) + log.Debugf("deserialized chunk spec found: %v [%s]", chunkSpec, serializedChunkRequest) + if err == nil { + for _, chunk := range *chunkSpec { + contents, err := manifest.GetChunkBytes(chunk) + if err == nil { + log.Debugf("sending chunk: %v %x", chunk, contents) + messages = append(messages, model.PeerMessage{ + ID: fmt.Sprintf("%v.%d", fileKey, chunk), + Context: event.ContextSendFile, + Data: contents, + }) + } + } + } + } + return messages +} + +// ProcessChunk given a chunk key and a chunk attempt to store and verify the chunk as part of an active download +// If this results in the file download being completed return downloaded = true +// Always return the progress of a matched download if it exists along with the total number of chunks and the +// given chunk ID +// If not such active download exists then return an empty file key and ignore all further processing. +func (fsss *FileSharingSubSystem) ProcessChunk(chunkKey string, chunk []byte) (fileKey string, downloaded bool, progress uint64, totalChunks uint64, chunkID uint64) { + fileKeyParts := strings.Split(chunkKey, ".") + downloaded = false + log.Debugf("got chunk for %s", fileKeyParts) + if len(fileKeyParts) == 3 { + fileKey = fmt.Sprintf("%s.%s", fileKeyParts[0], fileKeyParts[1]) + derivedChunkID, err := strconv.Atoi(fileKeyParts[2]) + if err == nil { + log.Debugf("got chunk id %d", chunkID) + chunkID = uint64(derivedChunkID) + manifestI, exists := fsss.activeDownloads.Load(fileKey) + if exists { + manifest := manifestI.(*Manifest) + log.Debugf("found active manifest %v", manifest) + progress, err = manifest.StoreChunk(uint64(chunkID), chunk) + totalChunks = uint64(len(manifest.Chunks)) + log.Debugf("attempts to store chunk %v %v", progress, err) + if err == nil { + if progress == totalChunks { + if manifest.VerifyFile() == nil { + manifest.Close() + fsss.activeDownloads.Delete(fileKey) + log.Debugf("file verified and downloaded!") + downloaded = true + } + } + } else { + // TODO if a chunk fails to save (possibly because its data hash didn't match the manifest), re-request it + } + } + } + } + return +} diff --git a/protocol/files/manifest.go b/protocol/files/manifest.go new file mode 100644 index 0000000..67d5fc6 --- /dev/null +++ b/protocol/files/manifest.go @@ -0,0 +1,312 @@ +package files + +import ( + "bufio" + "crypto/sha512" + "crypto/subtle" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "sync" +) + +// Chunk is a wrapper around a hash +type Chunk []byte + +// DefaultChunkSize is the default value of a manifest chunk +const DefaultChunkSize = 4096 + +// Manifest is a collection of hashes and other metadata needed to reconstruct a file and verify contents given a root hash +type Manifest struct { + Chunks []Chunk + FileName string + RootHash []byte + FileSizeInBytes uint64 + ChunkSizeInBytes uint64 + + chunkComplete []bool + openFd *os.File + progress uint64 + lock sync.Mutex +} + +// CreateManifest takes in a file path and constructs a file sharing manifest of hashes along with +// other information necessary to download, reconstruct and verify the file. +func CreateManifest(path string) (*Manifest, error) { + + // Process file into Chunks + f, err := os.Open(path) + + if err != nil { + return nil, err + } + + defer f.Close() + + reader := bufio.NewReader(f) + buf := make([]byte, DefaultChunkSize) + + var chunks []Chunk + fileSizeInBytes := uint64(0) + + rootHash := sha512.New() + + for { + n, err := reader.Read(buf) + if err != nil { + if err != io.EOF { + return nil, err + } + break + } + hash := sha512.New() + hash.Write(buf[0:n]) + rootHash.Write(buf[0:n]) + chunkHash := hash.Sum(nil) + chunks = append(chunks, chunkHash) + fileSizeInBytes += uint64(n) + } + + return &Manifest{ + Chunks: chunks, + FileName: path, + RootHash: rootHash.Sum(nil), + ChunkSizeInBytes: DefaultChunkSize, + FileSizeInBytes: fileSizeInBytes, + chunkComplete: make([]bool, len(chunks)), + }, nil +} + +// GetChunkBytes takes in a chunk identifier and returns the bytes associated with that chunk +// it does not attempt to validate the chunk Hash. +func (m *Manifest) GetChunkBytes(id uint64) ([]byte, error) { + m.lock.Lock() + defer m.lock.Unlock() + if id >= uint64(len(m.Chunks)) { + return nil, errors.New("chunk not found") + } + + if err := m.getFileHandle(); err != nil { + return nil, err + } + + // Seek to Chunk + offset, err := m.openFd.Seek(int64(id*m.ChunkSizeInBytes), 0) + if (uint64(offset) != id*m.ChunkSizeInBytes) || err != nil { + return nil, errors.New("chunk not found") + } + + // Read chunk into memory and return... + reader := bufio.NewReader(m.openFd) + buf := make([]byte, m.ChunkSizeInBytes) + n, err := reader.Read(buf) + if err != nil { + if err != io.EOF { + return nil, err + } + } + return buf[0:n], nil +} + +// LoadManifest reads in a json serialized Manifest from a file +func LoadManifest(filename string) (*Manifest, error) { + bytes, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + manifest := new(Manifest) + err = json.Unmarshal(bytes, manifest) + if err != nil { + return nil, err + } + manifest.chunkComplete = make([]bool, len(manifest.Chunks)) + return manifest, nil +} + +// VerifyFile attempts to calculate the rootHash of a file and compare it to the expected rootHash stored in the +// manifest +func (m *Manifest) VerifyFile() error { + m.lock.Lock() + defer m.lock.Unlock() + if err := m.getFileHandle(); err != nil { + return err + } + + offset, err := m.openFd.Seek(0, 0) + if offset != 0 || err != nil { + return errors.New("chunk not found") + } + + rootHash := sha512.New() + reader := bufio.NewReader(m.openFd) + buf := make([]byte, m.ChunkSizeInBytes) + for { + n, err := reader.Read(buf) + rootHash.Write(buf[0:n]) + if err != nil { + if err != io.EOF { + return err + } + break + } + } + + calculatedRootHash := rootHash.Sum(nil) + if subtle.ConstantTimeCompare(m.RootHash, calculatedRootHash) != 1 { + return fmt.Errorf("hashes do not match %x %x", m.RootHash, calculatedRootHash) + } + return nil +} + +// StoreChunk takes in a chunk id and contents, verifies the chunk has the expected hash and if so store the contents +// in the file. +func (m *Manifest) StoreChunk(id uint64, contents []byte) (uint64, error) { + m.lock.Lock() + defer m.lock.Unlock() + // Check the chunk id + if id >= uint64(len(m.Chunks)) { + return 0, errors.New("invalid chunk id") + } + + // Validate the chunk hash + hash := sha512.New() + hash.Write(contents) + chunkHash := hash.Sum(nil) + + if subtle.ConstantTimeCompare(chunkHash, m.Chunks[id]) != 1 { + return 0, fmt.Errorf("invalid chunk hash %x %x", chunkHash, m.Chunks[id]) + } + + if err := m.getFileHandle(); err != nil { + return 0, err + } + + offset, err := m.openFd.Seek(int64(id*m.ChunkSizeInBytes), 0) + if (uint64(offset) != id*m.ChunkSizeInBytes) || err != nil { + return 0, errors.New("chunk not found") + } + + // Write the contents of the chunk to the file + _, err = m.openFd.Write(contents) + + if err == nil && m.chunkComplete[id] == false { + m.chunkComplete[id] = true + m.progress++ + } + + return m.progress, err +} + +// private function to set the internal file handle +func (m *Manifest) getFileHandle() error { + // Seek to the chunk in the file + if m.openFd == nil { + fd, err := os.OpenFile(m.FileName, os.O_RDWR, 0600) + if err != nil { + return err + } + m.openFd = fd + } + return nil +} + +// GetChunkRequest returns an uncompressed list of Chunks needed to complete the file described in the manifest +func (m *Manifest) GetChunkRequest() ChunkSpec { + return CreateChunkSpec(m.chunkComplete) +} + +// PrepareDownload creates an empty file of the expected size of the file described by the manifest +// If the file already exists it assume it is the correct file and that it is resuming from when it left off. +func (m *Manifest) PrepareDownload() error { + m.lock.Lock() + defer m.lock.Unlock() + + m.chunkComplete = make([]bool, len(m.Chunks)) + + if info, err := os.Stat(m.FileName); os.IsNotExist(err) { + fd, err := os.Create(m.FileName) + if err != nil { + return err + } + m.openFd = fd + + writer := bufio.NewWriter(m.openFd) + buf := make([]byte, m.ChunkSizeInBytes) + for chunk := 0; chunk < len(m.Chunks)-1; chunk++ { + _, err := writer.Write(buf) + if err != nil { + return err + } + } + + lastChunkSize := m.FileSizeInBytes % m.ChunkSizeInBytes + if lastChunkSize > 0 { + buf = make([]byte, lastChunkSize) + _, err := writer.Write(buf) + if err != nil { + return err + } + } + writer.Flush() + } else { + + if err != nil { + return err + } + + if uint64(info.Size()) != m.FileSizeInBytes { + return fmt.Errorf("file exists but is the wrong size") + } + + if err := m.getFileHandle(); err != nil { + return err + } + + // Calculate Progress + reader := bufio.NewReader(m.openFd) + buf := make([]byte, m.ChunkSizeInBytes) + chunkI := 0 + for { + n, err := reader.Read(buf) + if err != nil { + if err != io.EOF { + return err + } + break + } + hash := sha512.New() + hash.Write(buf[0:n]) + chunkHash := hash.Sum(nil) + m.progress = 0 + if subtle.ConstantTimeCompare(chunkHash, m.Chunks[chunkI]) == 1 { + m.chunkComplete[chunkI] = true + m.progress++ + } + chunkI++ + } + } + return nil +} + +// Close closes the underlying file descriptor +func (m *Manifest) Close() { + m.lock.Lock() + defer m.lock.Unlock() + if m.openFd != nil { + m.openFd.Close() + } +} + +// Save writes a JSON encoded byte array version of the manifest to path +func (m *Manifest) Save(path string) error { + return ioutil.WriteFile(path, m.Serialize(), 0600) +} + +// Serialize returns the manifest as a JSON encoded byte array +func (m *Manifest) Serialize() []byte { + data, _ := json.Marshal(m) + return data +} diff --git a/protocol/files/manifest_test.go b/protocol/files/manifest_test.go new file mode 100644 index 0000000..c23e8b6 --- /dev/null +++ b/protocol/files/manifest_test.go @@ -0,0 +1,128 @@ +package files + +import ( + "encoding/hex" + "encoding/json" + "io/ioutil" + "math" + "testing" +) + +func TestManifest(t *testing.T) { + manifest, err := CreateManifest("testdata/example.txt") + if err != nil { + t.Fatalf("manifest create error: %v", err) + } + + if len(manifest.Chunks) != 1 { + t.Fatalf("manifest had unepxected Chunks : %v", manifest.Chunks) + } + + if manifest.FileSizeInBytes != 12 { + t.Fatalf("manifest had unepxected length : %v", manifest.FileSizeInBytes) + } + + if hex.EncodeToString(manifest.RootHash) != "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8" { + t.Fatalf("manifest had incorrect root Hash : %v", manifest.RootHash) + } + + t.Logf("%v", manifest) + + // Try to tread the chunk + contents, err := manifest.GetChunkBytes(1) + if err == nil { + t.Fatalf("chunk fetch should have thrown an error") + } + + contents, err = manifest.GetChunkBytes(0) + if err != nil { + t.Fatalf("chunk fetch error: %v", err) + } + contents, err = manifest.GetChunkBytes(0) + if err != nil { + t.Fatalf("chunk fetch error: %v", err) + } + + json, _ := json.Marshal(manifest) + t.Logf("%s", json) + + t.Logf("%s", contents) +} + +func TestManifestLarge(t *testing.T) { + manifest, err := CreateManifest("testdata/cwtch.png") + if err != nil { + t.Fatalf("manifest create error: %v", err) + } + + if len(manifest.Chunks) != int(math.Ceil(float64(51791)/DefaultChunkSize)) { + t.Fatalf("manifest had unexpected Chunks : %v", manifest.Chunks) + } + + if manifest.FileSizeInBytes != 51791 { + t.Fatalf("manifest had unepxected length : %v", manifest.FileSizeInBytes) + } + + if hex.EncodeToString(manifest.RootHash) != "8f0ed73bbb30db45b6a740b1251cae02945f48e4f991464d5f3607685c45dcd136a325dab2e5f6429ce2b715e602b20b5b16bf7438fb6235fefe912adcedb5fd" { + t.Fatalf("manifest had incorrect root Hash : %v", manifest.RootHash) + } + + t.Logf("%v", len(manifest.Chunks)) + + json, _ := json.Marshal(manifest) + t.Logf("%v %s", len(json), json) + + // Pretend we downloaded the manifest + ioutil.WriteFile("testdata/cwtch.png.manifest", json, 0600) + + // Load the manifest from a file + cwtchPngManifest, err := LoadManifest("testdata/cwtch.png.manifest") + if err != nil { + t.Fatalf("manifest create error: %v", err) + } + defer cwtchPngManifest.Close() + t.Logf("%v", cwtchPngManifest) + + // Test verifying the hash + if cwtchPngManifest.VerifyFile() != nil { + t.Fatalf("hashes do not validate error: %v", err) + } + + // Prepare Download + cwtchPngOutManifest, _ := LoadManifest("testdata/cwtch.png.manifest") + cwtchPngOutManifest.FileName = "testdata/cwtch.out.png" + + defer cwtchPngOutManifest.Close() + err = cwtchPngOutManifest.PrepareDownload() + if err != nil { + t.Fatalf("could not prepare download %v", err) + } + + for i := 0; i < len(cwtchPngManifest.Chunks); i++ { + + t.Logf("Sending Chunk %v %x from %v", i, cwtchPngManifest.Chunks[i], cwtchPngManifest.FileName) + + contents, err := cwtchPngManifest.GetChunkBytes(uint64(i)) + + if err != nil { + t.Fatalf("could not get chunk %v %v", i, err) + } + t.Logf("Progress: %v", cwtchPngOutManifest.chunkComplete) + _, err = cwtchPngOutManifest.StoreChunk(uint64(i), contents) + if err != nil { + t.Fatalf("could not store chunk %v %v", i, err) + } + + } + err = cwtchPngOutManifest.VerifyFile() + if err != nil { + t.Fatalf("could not verify file %v", err) + } + + // Test that changing the hash throws an error + cwtchPngManifest.RootHash[3] = 0xFF + if cwtchPngManifest.VerifyFile() == nil { + t.Fatalf("hashes should not validate error") + } + +} diff --git a/protocol/files/testdata/cwtch.out.png b/protocol/files/testdata/cwtch.out.png new file mode 100644 index 0000000000000000000000000000000000000000..e50812f7eb4da511c0964c3a9a061ee0ae140181 GIT binary patch literal 51791 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 z z=!a=--3WkM?$Q*Tfi`jbn#Jt$xZb_HNQ{+zu9cvjAsppb9JLU+i}?y??bhw>v8W=--o{|b-_>g1=WVn$cst?`s{OU)|z{h?( zb??9mA4c$a#W#Mlf$Di>y+dFq9kM39>2@V}q;fy+ovP<5b8kdh!BRlmJX zW&<_~t+&YJZCU?s-{cz|WB`M|FPnhObZEH6)aT{j&KpsBtDd32kp|Fo(kFgLov*=~ zj!(%Ho{UbAjl9R(PbFP-d_PB>$QvG&OyX9(E9^BH{Wge#7)~Z8vcDdV`^NjJqD(q9 zNh8<}`ihf(KP;jSOwG>^Tjr#pq4Vx398WSxoxIgyt|*km`s{G?h%W4(Kx(rfH0p>Z4pY_2hLhSO?T&B(a1a6`01qhY-yO2 zGkT)Ewx$YBVaa^cmaYrma>+2HHLND_C4J4rvZ(-!*|d7?NY@pfiDwP2J6+cKMBDbf zyN}+e^?jTd{P46W9VK0#WkMBP%H0n?*@XP=R(qY-f__bo^gFz*_aW*pr}tFrj?a5J z_UBJcfB!bTA*Q!pqwwEFDmY|GAvm$fO8~k2Gs>FYD9~C4a z1W58TOp>MtWY52Ru9Eo^p7rz7O;ec9VUF)v4FZ@2zsc zI1J;6;$*4pQ^1B6WhSN4RaI49ra!2usmJhi;e*QJWqVHfhht5OPh@fS{le3r=bEMVIUO!=`$VEt`yXX*BIHJ{Vwmd(OrY9kbo19YHX7pd#jscltS&rqE1S} z4Ni8HSgaCj)|WHo@ZAd605G6?XhTi6#Cn# zXWpM=mTqjQ{FeUIcD17B*(Ovzc2HoKfBT9y3>k4#DaV=F{P|+7TE=LJ>ScU>dlqS` zUumB1-*=@HPtTi5%(AYRau?(WT5u%n2)Xu;Qd#D8lnD(L6@KO)!x3Nh(`)>iJd>)) zh*b|e;3HxGvT(4vs%Tc?eQhlzI5kAbr}T~^8JNIK!P12r-T^Xl_pXnAkM>6tmV=|e zew7>E5J)9eefaQ!uF9tHqn$S{u@uzfS1ld2arnwp3aGqDyH!P79xz6P(sGEI?T^_l zFatD?DNud8?Kpn7|K>a1%75M}7nn1Frhx!CU+Y-M`SQe)eK66;6YqVn2H&AuUih-t z`ZkWY%iwUl&)j-nUy#{VPcWiZwDjR;W|E%a-#ZrUzdxy7due4{AWIe(4l<*-_~9AT zYq-`B)oUo!$F|S-r5`#8yYFvRLgh!rFHV-a27j1*eaS28@hL1sAOWo@55KYz109cM z|AW!CL`*3^621?OEeYk>j2WJfbE^NPc%O{)aq{Jh9DR;Jmq6SBr8jIB7DS@>tBBXH zr%>peuYL@c(I7TLRox9H^ZM{ThPi3`@tPqQSrYjW17l+W&`%Rj@A=15h}T29`kXod z8|HNg%kE>=6fE_p%q-Y!!1<_wW*I8~knH|~3z0PfYJco(Y^sjkG-E#>cTR$oBqGUD zFZ-`YO8kmZEY!7F3z#@PuSQEgH$R`}I{x^oB5jPMEj|LDmbx2s66iS}K54i`c~A;% zcmUo)^j)59>SAJI*Tz1n$}43ZG53{#?hE{4^YZ((i@FK&%-Pwg0O85w#@5IN5U2U= z-Qj?vSvr_rMlEPqV^%KtlcArk5GSdY@BG$%ZF6t}W`f_H%$J!|9wXV(ra5Y_`VFjP zwCgRNzBR4(tzv^s!xn}E1VWE<(g+%(B?N2=i?5=(pz7b1716dtWn|YstIZd~Mh!LK zK7nJxfoY1H2R2s5CD2K`*mP8W`>y0HYE8Etn|;&=`E&*)4(}QL;YOmomWwjYaAKJF zd+>>f_GdAYFF6u20Hv<@fGe3s^zdLH_Q@;2Bh4s7pDfFCRpiFRCN-UTfUceqpuou* z&~KRECrkGR)xaL+CrAF+Q0B)n#f!_{cNRD5@{Kp^`uf5evm+#uRyWq~_)ARCQ;;Gu zo(m`~WIQM-QGi)Tz5{W2s)b*QYv{>~mBj`0Q0N0MFHk^7w~6HmT>)d~bWpqUJU5TL zNHE6Wb3{p)Ne~lx)z7-)0b?A2>O{u0g@w`gV=2d?XhyB;!CNcvwpf;2KMN<{bzy66 zk)TuZV#jO&z(=w3)Mp%TPwNf4fi;=5Tl&`=7$p3o-QXGd1-FFxoeo)hH zK})H6JRdioLddi&>c|sx#0{mr2a4y6b!s$8N%EmpvVsu-?PMx&V+~#Um#*(aG_p=N zm_B715??zkW;Q%D)W58(%%Kz&;44h5sm|o0 zd!pC}6y<5t*mW;7m(5BH^&MUw_v@(s`jrh41PM)!VJosEJJQHsu2e-7x6wHUcc=qf z9VjrCS|ZOV&t1CY!58rFl1^XGS8rWGC|EU;ZuPTF#99%qWx@!Jm+c|3$g7ZOO5L72 z-}%Qq>II|+wDdh&wX{_CpEM4-TDMFwQ11F9yg$Y6ydlC`>1VPZ@{mx_Yq`k3kxr*? zEpiP&PoL0C13lZz8k0A-ViLA1JVM?$EC3w+ah6y!Kc$P% zV>W<(sW3xdb>cWR^Qlv(h{O`Bgr+B-Iy(G;?3B7qo=~qmaQ9*>9|?2eb+bnEH);Ch zBuiHJP4R;y&>z>Yjxb0|UpXm&f2RMa3!gSz=EC-0IgbuAC{cn`z;&(PQuTU&OfP7ND^3XfuQETcau7YW4 zKDXTNpVrNKMn>ZIJEeJIF*-eMW^rLt3c3h#azA!TC=jp{ZFjBk8d_ZR*n+!u`4M^` z1v7!LvDe_y5Nqm(Jh=$DVQlGB4#RN6(k=moAa=yyAOyuQCeFN8@+4^=9}*`Gd~w|C zYbHx#YGmOTHy6#%Z)BqA$zE_MH(;wW2NwKHiN22s85F4#`4uPIwB zcvRk543qBG1p@YBTZ4kjNY(rIz5yEtI-jH?Y2~o}S9pq1*ak z-Ujud^YuQ=0$7XFUB0PT*t%J%{o+8Y!}u7j-R@j9HY$?Otv}Aow)75eZ<2gS@8~~( z7s$QxBXMbcvETjkqO6aP&-7?wjoE~u$?u#drBOKUg&XY|uzLZWD@$Q@hb!c&owJ>4 znXVg&LeY<*;V~MYNe3Fb%{4r=@7S~{WT1erwzy{@XFMCX7G!R$HX|BW=bSI6}ZlK z<$qe<{``xjMLWu5{5BK5tzP7?v>mwE$t(0^9@e-4K>}N@odFy^H zI`?e%UtUU>;i8n6m$&JES1EtzyKOUk6VQU*PwHGj#xy0QB0f8^S~xIC5q4;Z2h@6^ zJPApnl)W&q+UjfA|IK2r&elPfCuMPDwg27j@0JV9aeSn5kEczsmoRr?)NmHI=501) zBJx`y>JHr2SPWhgs=57Kqt=}xMb3k2)rB9gd7s{2kAg_mA&dkxDQq=F)Jkjy?^#zw z&x$)WK><(~pf33JwfPh2Wp3^q`N-E>g6|#Zjsx7(Yw+pDl*Jf!smQ(3?bNh z_0`<`cYSFz(S%MHRe&x>5&>QP@{>Z9h4HTNg1xm%2(rt&w|W!Ou}5-LDi@dru)-DA zFQ&rOOYJ{$a`}UMFg_u6T{L_fN0H=aH-Htl9(hYbx)iaG4d$8d08R4 zjT)J;$d1^br(1>bM(TFKzM&KaR#sM+(vC94e}ZP%7ocp?bHB28)@LQ<8+1)U^czQb8+H#^A1gh68LF!|Q<63fW1i9{Z{Y`PkDVOSV;)aC=-^{)MZ*QU+(oz& ztw&~N?GItnbFzo4_4QEqojQF$^DNL-XaN)=PZ~t^_#eDm?a0K$#}^Ly^u7+^;s1ss z+LZ8h1QS7b5oeR&38M1aK$QoYU;O$&fFYWxPf+Odk>|)ms-ri>D%EraS+kE3vD#N6-t#ry9_6 z*Pxi+!Xvk(yZhH$yT=CTg<$+)0>Z;j7?SueU|hxEM|)KfAL|ZMi5oNT{?C{aWKuj1 zd76qrl$yX@Bplaeu7Q$3teotq?&GXDFBI+KvT(u%HNA28jmEKP1j*iK+`w%4lHVr- zg3{{mcd~8nuMzPQ_yQcYUWw12JIwuCRl4$HW$_LxH#ebf7u>ryHoLyvRX(ebrq+b_FLwpyPO z6e?LX{_rr9kJRXp{{X$|P8hoqicElBY$2NKbj5G?Lx;SeNdp_t`0QEa!}xtg=jW7( z^c13Bfyb@6wA<#11QW65GV0i66Z zvujSjYw>;>?rRt{ZE_`r6iu6-1Ny%Rx0E?x--Uvi^;Sn=%>PGVs;NOjc^v6h=9zaS5TA3fNGc%6&Z9OZJ)P$2 zqyld8QvL)U6d`mg=#vQHH?{&yEj)X_+PZiWpU2zVn}BH9Wg@%zu8BQn+j zxS+hK!8;21NnrQ16rf&Bu)iK_dA$2(2ze<`Wo9m}s%5EO?1KwD8MUVTrKYCH5d5xC zQH`lBvB_jV2-isluUm-;y23+ij1}nKB@Z0nXy%K6S7A3Tb{49QUHk1-dm@~a@;-V8XCZMrX&sU66%UV^5>W;1o-(MelCPXYv;3PtnRU8gQKH+ zqPD2$>gY5pYH&&^Zjq9ey?WGu-zshu)HRZf6K45TkvxKZ+yUQCpJSg=OWse5^-M?q z^;mBu2bD#9UR<#J0s^Xgmw|~l;8vr2qmqdfXVyKpe}W1nigHtAg{1q8!xjbr9b|edUTh46dae7#~iVBk4E?*R;F5q9V&Au~raJ1^2Z3`dLV=`9($PAxAK7R#;tGv1@t! zIwTw7!1)ZzGC4@+M_$k_;v%MHU>LFh##zA<`0J{MsT5;i;}h!5M5KMprf7jjLKmtI zOvC+igK*+a8kkmT5pGb24WrzP^G`m*QwDJfJz^pTYmB17Db@ffcK^M_)(8Cjqus$$ z*MDi_PCamd{@&_F>z{#F1oT$r<(*LU^MEbVdx#{b=^rd-d&}J!AO_MhG2uuZ$91X< ziahtSIsa82?QOh@wZS{@_c~l>PNjH-YwY*)7Zndl8Lu86+t18$odYuK@-ZDK-vGNs z$F+#D!G!SXU4;+;M-fZz9MDqOVu`<1UCYpYL>N~Tyl&Q)&I+k^YgWS4jk-esG*NpE zx!bPlb3p6}fLthGp&V2;a$2~3w2R1JT#c))R>dNzl|Qn0`g}wOR(NsG)uS(d{`~nV zwLzkM%udDNSQAYoqHg@Rk!xy^HYF(k(t7dbWO+S$w9WbY^`9C~pbAlRoA85LLBx3f z9!eb7hYyq1;%#8MXJX1_$K}WtH5-om6hH3tpJ>UOmkH1Yws9tgaP)tE5TjpL?8F`q zv?VT*k{PsUYg^|elhIoei6{8Jw00v$Jv@#;@_?|Ai$<@_=HGZin!JJcyash!p?_&n z>SE^-{W)@euS&EfMbahufrqxc8XI5yHiENI{_G>%77zokUr$|~@yg4SLPF64pt;Fb z6}O*%T;7JK*MLtK5gB>3hmG{&vWAC;2SI8XD4mbHkJ%Pu?Pwkl!He*jjqTQN$*yhBBJ4+eH+*~MvzI~tNOgaZ)CPe4uzYVvzSbr?O+wtLp z5xsu)OYT~6bOqSAcfKp^sg;E=7j#9ViDiJacp94pl@C7E1AYx85s)YcECZVQSJz3{ z$bR!f{6TA`;}^ZY7!_Am@|E7)ZO(}_SHe+%RxH@<2eJ&2JBOqm1?J1FuS|1x5}E z6aQpUm?DWPulRda6$x;e7j%0$w_AF$qPP=;90+j}lC@HC;o6U8s;&y_)zpcDd|@_QitvhItb zrz}A}`S|*}FVaB4gFFwO^zlE@zx0kZJ$R|xx=FVC011^S3RKELvZ;#Zv^)ZnCWJ@k zVk+Fw3}ITfhO02JAsh{1stl$!VxGmqW*_e1RjIREPsGAkWJn0dyYpiU_d36P6dmmk zK7j7$>mm3Ah%AuO8^6g>?Cow6`CyFOzY&+LPX-;yYqYJM%M!iwpTS?h{D5sST`;tK zdr4vEA$|F4PY#OEH=tAGKB-|S+GSqp;oHZi!DrmJ{|Yz+XgYS~t^YwPVJ)s$2r_lm zD@Dh~$L&#kl3~kIitE;=;WA)!b?|WTiWYB%l#9F=n znr?!gp5op;UtQ8Kwe^!kVAa+g-%h@gfN8aXun&OCSD%yCfO4<9n;VEW+lO7164OvS z5$>zG8-sVB{f~cs2g)%2-_>wF<@=B{=D+bj<9iA)DJ9iqE%aRhJwyy4Y8LI^>NN$F zLPadYCBUa8$mQWgaKoOo&3%5gb#)U)Bh)Wug`q<8J-@vsvzc5U7&mN=*m3>v zhv^)Ixb}VJ%eUYU@gH&?zV7Ak}!}~ zLFp7|w5#jY8CF(dU9X(U?L?d~X8rQ-Nn2O~37wlW7PkOpp!v^*3V*9t1}|1WRw1^Q zvYouiFW;oN)b+Uepf zSWp}O1jsU?2(+N2H&A+~VueJb_>}p|#FQJPhw<^|c2}-g@u*xpJ30L5i?luc<(`MK z$4yN+A*CDZnsoal6AIO;{5DEBdEoln2FEia1ILF4uwpR8A4L9Xp4YG9>C8w?Z`6^RM~{3sRb03WWUf-651Rb7SG87dA#xAXggx@h!? z&a6dC=?HDnguVxxIFD#$iCyIIeexliBM)9xoSgd|%kyVlHY_cWJn7AAp%U}qv!m8r10zn{;;V?+J2O)y%$fx$u5uhh!Qo=dBdtA}JemOU@Ly2gza zh}GS11falp^yPT{F9@m_=l*@?1dpMDn4i;;S>mvj5%9YT#q}O>+=yn~WkwTEa|;VA zjy_N17px!;Dw<^kvp0s;-hrEM-<+5(vi;dyd)&ecN88hFCS zFdD`_m~NR6eYEFtGw1Y7oF8J!S=vvcUSdaKQj(3GoO3m>3P}WXrpUcIo#)dyYPR#~ zW;$ZJ2B9B8KBpX}+z=?~>g)X3MU7N&?GTm$c?DNZ{GXHuLuJIpx56D$1&=&1PpXW@ zrKQs}(Gy0-FJ8a?ClaUm@a3Y*F}!4$Z3R>lJw2g>foqH~7@C*}LvKC3@Q)`z-4606 zI{23|jI)HDI`^+zP_GB zaqJ{dLhu1(i!NW%?ov7F-o5)*j`#v+f1e*%qa?W+MOW`8ER#1UdR1>I#y<8`z)+9v zNR9Htc#kEKnsn&i3LC2MuWyP~2=j#kDBy4aULjCOSPkzN%WWG>nEn7zt1FKZ>KLRe zw7Oo1n=L}_3WA5IqHpfegN+ofmE8p%o8d`T(NS#X(!A@ddv!R;9#6wD6q}h@5|g6x zcF)kh|4U;S`<(hfGp)IW0hBIAItEWq&w8z$#AFZ6r<6mZjl7Z)blV((fz3Ix=X5|} z!k4S{_l{t+j=QJy?mB=v5eW$)7~h%b$khdzJyx3N(4-{19d~+KIWmhOi-=hwu&v9@ zrpY4vkLl``r!6&0q+SQ|VVq@l==p^ZUoSIqWntul;&5v$PP7sd-IE_3{$?8Y1F<(w1Nw}3N&a;v2(rbx zbLY}DNxKvBS5LwzrHN(WAe*Q@YtD%AN9({ss!5EFh@=gfbh&m-6$H5BXt)Ix*?-d3 zvVec;$hh%A=nFiz>gvkJ&~7s!ToNNG3tcO$eV+<1a-utm=(s7T=d#graI+0tw2&&n z>Nl~bYA~gzt*t-)QT3nG4n*BDcm>h$_j11>A;RrG<~N2?$=pLkuNxm2w9|1UI{zwK)}&G zUi~$N>E`1eWo14HJ3IVbCznZ=S&<5q8OBt2^lG5`si{pfQvSs+Y!4%*x8rgl^b-gH z-vRXM=42n^$+ly+=Krt{trBB5FgfUSMamz)*7bs72CQ)8q4og?!5D&Ha$g9S>>LtZPPjP4eXkQj=r zJwzjN_*eyJ(GjjTWW&_M764s!{n8PTfY8*_N;|gd@0~a2pgeSk!xwg=`b7gaVzK-C z?pWQSW_)>+0B?k`sLwIP!l{xHOTuwL<1KP;SL%gU>(!A>1>zM^xE_^c^04K>vo+vL zN|&_l{yhgqaiB|&rx zz{Wsq9ggzf9MyPiHQ(=qncX&i@pbtmTdnTx92=X1;af}f zWC{xld{U4eF`K+PooVD>35zIHCtl%gqWI)_cER}#WNnG*gE;Z!lR^Kn1=JGn9c7-v z4uVFFnSq>$CPI(EbuWu)-vbK`ZWo^?T@JmK zIlVhYU{?eLOADg2lkZP6H5mx-qp(r;aMPwi-i<&8^CX^Hzhi1@0!>({V;4op6vy`@?_`waX6chu=u`l+1&hM+nTZ_q-|ezN$fa$JE~x> zj@s4Z+5xlnhJxb{E~8)T648;_p>p=^Sr-i*9YUtCm50at^qG#`m&1}!ppui5(HBz) z2qcS$i=Vrj0~7;?6>*&p(6~CEOU+kRF*1^oP$dDz!{Uvw9iIzm7~OF#5id0^zVgYf z;E3x^Dz8Hd-!_2J`Faj6U1CbAF*6CK>nW)GgLl^+Q5Hnob-^&o@3ygp#aAUnX}^f5 zwDz4RVQ*1-_hM=0sOD!XhV3>wrf*#~JvDhOyE9-dAuAjYSZrjk3s_N@Yf{~9d zEyBP}B-`MYs6B4*L{yd3)j)=>1xfhZ9A{dTP!UwIqy|!`#l8X$jks)op56bhQgPVu;iHq02G(LjUl~C zUTka$uh)Hx#?ePuN-+d;A6OWbXwi}99|dYq&@gV3!w)=wS5c?G9~~vw#2Q2+-5dIq z)O?L(s_F&E07&SWC#$coZEjHLv;EKh=xX}fj2#LS!dlroPUPN1MfvSK>@gx^p8O%! zll$}MMFbPs0waUAQ?vh_B??>A>c0FQMic*-}jKVX+ z&J13RuzuKmgZ8g7P=&ZC!A4g@vLfHTT*WG(F8EmjCGx|mBRVx_Nc<7n^!T`fWKLY9 z(0zHp4FduKYB6ggHS0c{E-c^eTVLqNAetckN;WC87RQ@dM3T zZeYHc&m|7(E8pMpA~na@JnZo%%g&u)7=u%fMGBXX-@LH~U2Fusqa_eGRwz455v1}^VK!$6u5$tlYjY= z-Z4;MCJw{po^`j9W0?R((F6J-7CYxQoO1+J_Qvt(uZ3V_65tUa9KlLb(#BC$)Vy^Q zv!lB&zM%bNUnPDxxQ#2WOLNNtW<)Jehgl~pk(=)P_7)b_p|>uXzO#Q`VVJT0*yj12 zN`*Ju^%@bE3?A4E$2Juv&IFS}mt&fm)Id_Cuw)#=m_=sEdh^t4DgvQJJi)7DhwHY} z=(TU=wB;E(-IXD#homU|U1&%M1Q6zlLh1V!@|)p%#lTo_D2ekzuo4W^rU@@J zWYO^AalrjY)A!~Yo(2(b41>$C)sut-FzghC3wjx+rqV@a^n_qb)C${CH$Ak6Sg->% z6N87#OISRR7B~3sAEW0c3A4|IUEVGBy0leK4~1RT%D(!SZS>D;>|h9+EVx;5IB+7# z7!&3J`{olQRkQg_f2^Y>hFPq+{M_+M#ok^B69GX?+2fjo(AB44KL`~p6ROR%J^JFT z^Mc4AdXa%{$M5}eOQ`V03OhX{i@8Ju%_2=teOgRYNy9DL1rRikZZ98UtbMs(K-^ocy zpNyFUSyON|VLgK0!9g-{v9z+;R_@%>Jx3J8f#_p5#a-w$~1uIIW^KCKzD zJ=!}Y#Gv?hnra;1HzO;nFyQ_ISoN~HFkC!a^X{#4z2x^xa+_LNTV?qI^n}}6NRcjr z!J1pBDS*O7z@!#`^~6!^HEm%aH#RoFvJ-G__>BB}94ig?%rp%g(@=47k;Y4;wP*F1 z9DbC$Q`MCgZ^v2<&b>kZ{Na*Y&_>^#$vOrJ`L~ir;l7(41U_=%LgrY%CuwEzq#EMg zEUo;W9=^jtq$r~^@<(ku^j(o7=ME$9@}Gft2n(le&W8`@e0&shb940#4C1_J#cnC3fHW3J&YmA}QR(PHIB>t%!TSjW?(hbYt`;xX*dRoLldl^m=s_|`TC~$$51KE-wlgc;> zp6?i2T#3E#4D-qE42%FR``LnkhWLCc8SXez@e#OQwcC>gc4W=_JB)+E*H_BFPfo6E z!kBD3qq!%utH7_I6&Sm{^Zv>?XHZnpM&`stLis&=`bS2ndlV(f6ldezse;zJD|3p9 zB3f zv%o63%hhYwrk=0V?_KG*pGv{B$5mTPlEWgc9=Df|M>j)If05o%k7i&};4 z5DK3pC+E(mfE;-}3Dg63wlRmFZb~Unl9C{VjR+imop^ts6A?T%FmSg1<43}1t?tni z1yJawbPoaBr&lqzv;7G5vsaItdii3IEUVny=`QI8lA54ma0DpO^6Kg7!OW}cS`A6G z8tQ(S^v`U{2wI%6t!lL?rVbfyki1TdAdtFS1Vb5SA{u>50Xg#qc@iFtOkawNiz8XO zEmzGjfE|U?kULN;U|gX8&ue+G8qLWs13w~b?)^{Py&J2mTvnh*bqXEj_M=@u*~9uh zFjRXHC1YRqELA@X&Wr2fFy;+DRE6(W@;HED+Jkn?EG}M69+qhX0AS^%JK=Hs3~w#x zjDZAuR{+io;roh|sRZxd^;TDJ6tl8wFhq*+_fe~&3M}dtAHciRx0VkYWrO*>Fp1GP zi9vwX=C)Q-(Q`~NJ=T?xnvf#A_KNu8E{LS6!<11#t+>_y;{ufSJMD+bI*|2Q`SNE; zijhT%!ziH8sZ&Qm1}1qUU{Eg<+A+g9IfN?7J38(8Zntlz!z%XK7}qwTKoD5QwcQRk zY!$-Ek-2RYzNO$Av$_Q+=;BEXML0PX!B#dL`dZQg;^>Pv?ph)Uw%eg=rT zH)2uA>y9#goo$I+aEYRUOs~NC7la@zH%iOP+h#j{}2wPtPeVC-ZvxLl(ikyv6H=D z9lYa~B;vhN$dK)y^ba<)-V}3MSCSE)rA0Y~Mk50+Nph>;kkJYm<7iOt;Q(`)QY>Fy z_k9qaK4%?!3y|96b?vuR2%*|I?{_aCvOakxnDJc1$-WfF00u^dKT{LP(}boJbEpMP z?Ho#@&?BJ|Ogrb6=>Z3kQ1gILgBqQTuNOdMlJ8nZ{N*fCL2xKY99;q^4U@&7TQ3sb$Lufd4f+LnM)1H2Lxg$P3Kn5|Ln>K#cw#{AnZ9ydjsf6}*TPr}qZ^?ic_4@Y zhbS8khaPoth8|~I`^fFQ)nJI)7&g4x2@{l-^K0#yolHJGN% zzxj!ho}PZVt}rW$3`&x!)ixeWwvA+v0f2#(ThCvh7t@G`{6*f{W) z76ZQ-QkGj-c-FNP_mVrV?Fgca>bu~3!pldxep~qRyAgo{E;iKL7p3s{fGI%oih_gE zAY~XonGplBF2XW0A4O#OjR@|-x54_f5TUYlE zXr5E2bcf$?|MWZ1mLxn)7Z6abe80}Z->T)*3nT>9c!WLX_v0lQb3!znl;Csn!Pv;? z4{SRJuXuCh2r4q*s8Bk{eHRaA<5jo6ivQBbUN~y%TC{>Pj7m3upL!6Av%y4$4 zM$1avaqb?4ypD9C=iKQo4uV}t-TFYxHP-CzMWSZDQ4BJar)46OWL-O3vDj#(15%J>nP*xK`v~Asfo$yMevxwrSGOTNZ$N6*t=}z z=60Ta)4#1`o6l+e1PScw`R$tSKkW$`bSifx;R*5s)nv<}#=r`usp|KZYn3>r;5`V* z$S?sBOlon<9Dc%>NpA!^>=q?2h6&=yT5$l1Q~#yqxc8};YL+F zm978cqO|giPfNPamvZWki_(p1I3EWgC{%K;ouSF3wT+}?yL2Av8CBT1S%X&E@~Cv( zUsH?-tew{G*1vmq!lUO&y4v}R;l`AqC`HBZkhZXlCivL~#QrRb{`@DYTa#FU zb2({ua)5<O{Bt z9f!KTW%OsOR_EKdn|^gvzJB}mSMu=o-rmewZ>8|rvldP-qoZkn|I6T8JDiVZiGu>R z2d5JHAlT5<)E`g$66S!6+Lq#SU6jVIq;zk(UA*|^9ulogWlQ%7wcXJ(8#ah6WIj7B z0K`XZJO91>3$A^i)q5c>PCxyA7=MkG;?}L7Bj9ADSX4ZQ&&kUJZ7thJ4$#M?g_)VR z@8cfyAXUg#pivEbqj3*T9C#}UP^Q-3fhC#?2gggk%PXTd1NH8|&B>Vy!@2a7nRgoq zi-~yI_Q;Wbf?5H zdpOn4dmg-Kx8kH`_!CmWzJe@M5vZJ!X9pa4)4V)f&19OlPHSsvaZ0kU@fkb!*8-%F zJuH^0K8TZgo|H6FS#9bY0E2of(!6ED~Hm&;ZgY;K&T z8)QzM`rvJAYruvGoHOHfkl`eaF#vc{m9J;cIhSrncUS<1D-Y)fSHf~{-g8M&xP9!0 z|BTP;Gtfi>&o3FM9V$YK{Us?wZR-B6i2#I2J6k6(dsfG&|Em7umNUDkIa<$|i+qg* zv9h$Y`+`_^s0kR@Sy`XcEc7m3LuEbyp6;X5N~5-17yiLAwSD7HJnT5H>`00Ao8`T% z&x9bk(Ufi17(Y_B`SW45j9R&{X_OvhA2W=NHo}^$mFOFJwr?8kIYinO|R)un9|SI zJ(9h7bc%PjbBm}^-O$i<$!~31A2oIS^1E#eYCiyX2AKk$cQX`2kIM8kvG+KYTtop$ zW;pzB@l?5UNe~$a^+EsT>e(=do#_~9!ia4GExuVlb>?{9cZp4&6E*72NL_n($q^(m z{Q-d7=B9ffb!J+(?HW;-t%&lf8icK#5mZ8>sHk{;4cda4-j2cfwYGHe_^+Dd{A|dN znG-mem;nvD?X@3(kgEhqvY|#V>FKos&E+k_VRdzY|MpL9Uhe$|x)_m+AmPn*H8Af1 zyim(Y;L639d|0PY8bq3jhi8ms>Q;$2()i^G*XKQ;lV%$X8!%_moA50SGLx<{_c~%! z)o|gGKoH?I!Ed8ImP@iM_+%JR0>=f>=^70Rao! zEcVLw_9G^~5mt`{)Cx42x3V#789*BLp+77bDw>@7tbu{SGid-`w4DUvZRk#S_NceK zA#0=+rD=(;Vc=FVTvBO)co?+Wn#gwta@k>SFjBPb}SZcgdQzF+1ITL>q3%KyE&;B1WO56s*-lUgI6@U46}N7?R)p3Jf=rlgxZ5aYJpb;blb+qX#%W zv%&+2@2A6ZWRf*DZ{WvHBkEyGyb!gcqNd%%mVD7rBK{mu`aoT!7Rb48x%!oO2Vjo4 zKYtt&D*~$3f_E=kimzIoRfdfjv&5<)0bZS{4Gkg6cL|ecl$4C;sKx;7edIE99tbMy zGTXIYqr^)PwSZwB*)`^xElLASQ}O&@N2n5l^Pw+sQGhej)VJ1>V}%$~w?~By-fN-n zGbC3&0Ul<%Q_>4PL@z+6Ifj%F=*dyLP98Nx{FUL4^3Gn8#&IE}3jZ~JWvue5)1D!D znVxiLgE+i*N8+KyYkYgl+#AF?cH?E*gGfyZY=i-8@DegoTRGDEbU(;*u%sY|x~c}W zLnLnQD}l*%wms7sd`LE6Mjkzn$^}?h#PeMpJ$fG6I||ysHvGB%SC^Mx%8hagxM2)w zhqE+>g|oN_)^bai%yl?O}y zxJeEh@uI+fxhcU8sX0tTzJL-uD#z3Hyee9v`}f^t)LotL;-sUzwH{4b@fkLNS^m>OTn3=babq{d(-6qy(Ph9!Umh4eE+v^qWP}c{<_REz>bwL|25%v zSisHGdhk`Y?X6VqzB@x79X0}PXf5iVRmZtl+1Gvw(ZWQxj=>mgEZvUZVF~-brJlEU zOy8y^JLeVak|RvT@VxwU*U8lNTMm=B=ytbdH@^v6ug~cZP!U1FZ+`GFk!2_Khg;>F zY)zL3KdF2A|3M#N))mM|)ezJi?>Np-GKPm4psbIZK4o`CXQHuCq=Uz|Ca|l#&y_5a zY(7B&KsRHv!2;TKaJPMZg7At(Y1okTcp4<3-P!&mf`!uKmh0C1nY8M}>nAn@yT^e75@U`3_p8#q`$f+m zKZZZS7u+ywPxYTw#HuMxfvqyxfNB(e0ds+-`jsp3Wpn@{`QyunVa{TnFbsYk$>}?l zO~b<+!0`G!ih<#``@VN;m>hYjy5Tf=zdFIfEtUjv?ibpf!4P!Ymfh zHyT&sh%COhqKdmMNiAKI=@x0fKr9&laQup>1nUh1JYbFi`h9+HPPBlZ%Fx8b7KT;6 z^!ytDaV(6<5o z{uZF)!{OlC@PwEGMY(%`a5`D#HYN zjQ`(`ldF{t2NSPv+qQAu-|4clZhH8>DXA{>$2cCwiI*FQ_d)i@z)1ko2vG?M*3pPJ ztQ6W1Nl6I}g>q$x2promN=&^nvolM~$vg6J)LT`v5yn3~hAsVU7l(TJYJOPDOg-Yb z`B?2j)+|1_=(w;j*;TcjFv9(k5~XIhO4^lnW?ytyA_RB1cMbqYmFf8Ejv@#kQ=j*! z>FHacHq!lhQ1w*anG6Vcp0jE4)=DXSchI7u)W9X)#`P}GJAGyFYzHjlX5hRgIR(Yh zm04KxEI%Sb{dILiZHt~TRYF+i0Ode;vdoz1`@rPP$zf_Z-5PrwFn+AE&&pG;Bg|Q0?eti3mUz12WRX-054Gm#prHu$Bp*T{1KojILDCpI#wXK-`BMmVtrX4gH7WsEUvJu#$wl>3Se7u z2adHZ;PNCqqP05qBO%Yyj6DBFB?I(zFWj%6d8Q0uYkTeuk<_BhvQcT_+uUs6hRhAD z-BLjAFNILAJZoBO9HhS#Rs_Lp6wV!8Xi?jB_4F+OW}VCz>%E7sq@AqO3>y-jdZNwW zI(SvuV|)3PY`8Xm0QpMYvnasKX|Ldv;Axq$*FMzw7Yz)}?!4a7k<1(*gIjdo8l)id!a`(>9dMv^9M6jXVHv@~b zc)Qphoo0qWBAh!~M&GE3J7bO?uV#Tsuz`G-NEEHx`cXTO5my`CWZh_R^?;l7;2?kP zjGr0uI|L<+R*?NrG+Q4Q1CACn-jg?Gv0824^hz!O28)`~1b0&&B+$kG?W1lNhjS4>??OKYO@6bG>rI^>+{LA>h4_z$x#J3cBS?`{zf}&VQ9+ zXSS7MTBk=SSz1KkqCVRvOIR%2NU-Y?gMT%o(P00%NLXF%hf7u;Y>uts95ZZS5T@h} z;<3^+>7-x-wsv3(|E+8ilwL`$NXeTxHT$?Fa*Z2*-T5NlfiqRj2!7!n9#9_QFpIjF%BF# zkKOg#dV8+g@{J+@tC-==Mfy5XHgA@TOpy>ePKqlEzzV`waxA(MsIU^y8)1Zj+%*T|%EJXzA-5>4_H{7XFFHl`Ri^te^vH}wWyeOEHw=Az+i?r`5!x2Ao#s0K{ zJRc9i?-5l0r^%Q?gcDfI&CLnxgS36) z+;n^@hQ6r+o(=>70O;AJEFxjBj{a#m3?#VyYuLJwM||w1r2*~Z`+H-PnICjGsJw56 z8+rElD2iV!d!29o=qMq<6cn*#B{7lV zIJljTswxx3_iGC@i5Knjkz{|e=JK@sdnv546I6UiWh-gwNG$9M7B-F zXTgxvb%cg#@@8;#!{LVe_B5^Kr?4Z)6z__80Xu{vCP}jO>yU`Z=5}`X;UpesiGte6 zDH3s8G88h7Xg2YWb~-0Wn4(Sw2>G>LVC-(S^qa^YW1%Z@By4SM5&JWShlg#!Wr}3X z1G)>)O~&eKPQ2A&0VVJY(1~m4s~?5-8vohtDc-bCn^eeD?wyMgQc|K%`NEt?RilGk zYXOyvrff=Zi(Z)gv&XkGlX z+WfuBhR~1-zZ9_UI3P&T!5i?IKmQrJsh3~LQEW||zQHku8UFTds$%TjoaavgqylGi zD)}EY#S>E5%g)1t4wuzTJQ)(luSyaJt9eC+0TT;2pI{s*)V+R(9m1jaf}50}AVM1N z0Z>-&H2r6o3X}1eYE+`q`Q))N6_O40SP(>862TqF{`$tgygQV(uT4ys22n-5(lq z1FV#>V9X9l+M9Rp{%D5`7u@g*3tLx*5e}bEheM#@?y{3eg1!%e&#o@I~=QSS{R!9<@dX@;Mp`PL1FY=gfISOHtC6Ip~ zMIgRu%D9G7w=OnSqr4`FZZ9Vd;xL{i2==6Br(M$Q>h30WuhHvYF{-K)*}eO!=j`o| z|LF<7II4DxL2PwvE5yo|T3CP$A+J)PC8RDfxt@}gY=sH9kP^<=Dh9nhzss(!lJEs; z06|OMltszz3t=!;y@M$URW+ecIv<0uMItOQFL^BW>bSLG%Qzt zJ!|MY0K6x4?ftn>%uf3KN`8^#Qk=_gE!!_~$WuGV+qwY(X8^B@KFZS8+}^J3%Uk&p zmT3fk@+{%rp~5!N6e12_;W{u#d%>5Lir@pC0ejr3$oqYCNcF>A9)!d0z0*}+UnSD5 zaY)Un<+}AhZ20##H#1@$f_M{7pI6^qhVxL{mpV&Y;fVVE7KhR_Xl`oLVsF?x-tGk= z7c_Klf~-0}n5>k{RI$~ptt3H_2HQK-O%@+=^d8Pd%KRjnqMsufC5VB@yDEkaE%844nL4{`ahE)`%YV=(l za`Z<=q^de3^kM%KMxBcwV#Cc%r~pI%aI>-jJjS~j`0Rcyd^%7)2e+0UxDYZv-~X(W zvn{FnPg+SR(}8CUqhFS4O1JS3$Oxp6@UEWeNI->1uDadbl3>yBz5CR|K+>#D-Qg|| ziGvA@XujQKNGV}PXzMnCm<}NZbGRyY2rI{<^z^k6o0!%*Q(u~_tA@y9XJ~7Uy2@<# z*wG1AQ;e57#o9tqFxHm34KzU5P{%n29geT{eaUCK?cQ*5-)XR=dYtP=+#M_L+#=?Rlh{ zd`Y?II!bNGrnstkFG}N>7;>@pf3Rkuw%1>#I>KjK7+y}~)2ssK##AVyn!53j1HeRy zmF{w{WT4O@(WKJQ416DS5#;D|9gTB_e!c;Ff!9Hy6tn;H4DZ=FcIR6~4~aON;{BWO zq}&Y=CT-CZ2IGl{Ru_YpDkRmQC`$M$Ps_y2EQF5NRa8z08Q0HC_BFGR0!%1?SLG=`UmcB0+ z*b(p^C9VBG*F4~-Vq*CFBc7;`m{0a>`po8q7=uOneu zLnjct{v<{6?_Sgz98{A3IjH6!Rb-gss_@@$!RSVet|}2n`1^n`@;7;kd|S_d0Ip^0CW7lIGVy!0A7J3*X4Ir z5>-vcO+9daw*!q0sQ;3jr`__OqennzcBb)xJ23WQ#>Xu{n1WMJZ<)w>8rUzSIXZK5 zF`!QaaVk3?9EfTpEe0^7rttFGtX*3>fYwDVh*+seNlO=*`La)|!ArRklaRouZ&c5y z9=jxwrJ=1Y0@|X`;hYr|uLebIDBzsU+wpVF^CX<%X!?XeV z1Q4avZES=gN$msMhV9+mnzsj|qvoas#z9+_Y9z`ffP_%TRlRi$o^Ds3y=|OlWYzm9 za#G3|Q{(f1~_*md3ohFbxNgOF45t9bIUv{0HRIc{@U!Ma7gI9 z1utr9W+t?)O-n&RfmE53T2vsh3`37xq&dao$Fr3K{=WUSqGiCb3|XbkdVovz@X%?J1La@zyXOA#~mCTIG{$v(9}Zw4jE02CkCdjT13Go zU0~IH7dmxg$V*}PUHns-4Gohcz$Ht8^x{j{w%@8BT187IO? zVfd68xb^SA*^LLKbl#W!{5bvWNGoRstY)XNi^AmH2-7XdwwxCh7TS(%Taf+(?Ib(X z)ah50A;QPl5RDvIPBkxI{y`%Z*GZoq*#mebIX(N!Ay zLk&tXB$5@T7)~N;$=-IP56M$y_di|Dh%AO?pXw## z-+0@|-a95HMyUg?&jSx&K7T07$M>FYNSnGqWJ~j^PxR;A!Kth3kZnY!%K+<9wDFKG zGi6C8tg6opOKh_#4ibd7R4`{GktME_B3TLO0@2V&k)|;YSVIGzODxz)hho$EmuX>- zyZY&n{(_N_?fKYM6GWq{=lmC+FD9&;i-46%+ffPqy5mHT^h@TII~6oESP9#1D+Fo{DbD)0 z_x8>zj(&}(5`mX+0}TJ4ANy)N0NjZl-3F?n63B(X{!zON0O>c48hL(LNT@FGrtyf5cgXd24?k&l&CV{Mc{bo$!!9(_-pk+EHpnN_A9*)lB{5^)MaWk|ui{oc^G zZ*P$*u4}tT76h>q)Pfg%l@NM_!7Kg~GS(H)l@5(UIoxaNCl6?l^YvQ?jckm9QQkvV z`b_O-YEe_csIaE;m5yP#@MAq@M;moHFGNlBNT_%D@v8`)f=+93?9RF)T|bt)`%Fyz zdIK~4u#}7o>RJ9l}gD!7S+_5QL-DtSZ|~!H#e~G_3NJ&u-ns8S2Qx<`zmAj zO(r9wd!zWdrliqO@8i@{hq0?GjttM2v7M-IK}37KRB;Y21J_g@m*}ifL!*KvnEdHj rT3TW^o1_&AV>(a$|M`b+orua?wdJnY@dnd)1kusFqEUF>`r-cp0f?Qr literal 0 HcmV?d00001 diff --git a/protocol/files/testdata/cwtch.png b/protocol/files/testdata/cwtch.png new file mode 100644 index 0000000000000000000000000000000000000000..e50812f7eb4da511c0964c3a9a061ee0ae140181 GIT binary patch literal 51791 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 z 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 literal 0 HcmV?d00001 diff --git a/protocol/files/testdata/cwtch.png.manifest b/protocol/files/testdata/cwtch.png.manifest new file mode 100644 index 0000000..826a093 --- /dev/null +++ b/protocol/files/testdata/cwtch.png.manifest @@ -0,0 +1 @@ +{"Chunks":["2614xLRT0mPJYSBejVhB+xfFMSe5sM72qSTDBn3KqmmcK89oIwVmLr+2X5K3Wpl2f1oo3byyU86zdJp//dwTVg==","H2GcT8AZcy65Bbov34aVFGini5c4awpAT9Pcj4qamN56RkHQiLdtAtY4Lo7YlD2XQvfGF7bbfTt15EUcY8G2+Q==","YmvYk+5Ds1JB6K5YYZsNCfaMn7Qciql4iWpTxgHMz2a3uTpibGTQPW/ja2B6x7hplbhyCzkqlPS5XZAM4bVxxA==","1WrybcOYtRmU3QaGv/VEjlRSj9rNvFFrB7pw4E2NvN5rDt2zjMfHTIAT69pVHUPm7oRjYPGX16w0rg9CKv7Eow==","lz5h++lfGOodW+/xwpsfQz3HdTqTZYczGqnpkpoCH/6hfUbGRlnOfWeGpovKR9c6azzJf1ciMjHCsE3T7ZiNKA==","gLf58jjGMM/SXpj/1DDk9qae/EBHuXdZ9lPZXybu0/ZNwsPHjf7hqgcVlKQnx8nfRIuy/LR5WTdGZPAklWRtbg==","ujddGeMM9b7uTIqopSW63aDZYsrvHbXluhcpBUECqr2BBxrxvOK+rHFrk8HKk1JjYWyma9UnTmWGUWj5QHGsoQ==","dYzRAfWCgrxgB82+JcqnXLiwa4tKNDb4PzBXuW5uPKhYIuydL/FOJi1SWGrBP1Es+9UmmPnFaFyy8IXVUOLeMg==","Saubl7U9KePb/4VCm2X3yFrNFoO0au93JFu0By1klmHR+3Vz7ayWX3aCdnSwLY3IBdjcsvZv9xQ0IafdSy6JSw==","enA+R1ufZNlsZrwgJb+HQQtuBLlJM0sCzpJ2lhGdTs2yYMBFpVwNo8/Z/1o4OOqUqVnlF4u/A3L7R1lgDn7VYA==","ywykeEMBsuTgLwTXu/4kQc79JDmv0LVZPo+spV0PhrNBX24PNlm7Fo3n7H83N5UMtSpTW7PtvXOyBFd+m1hxQQ==","RFahJ53i1/LWZuAFoa1ey7/qPjEeVyG6L4UQgXfKdfxUj/XoMqDXKAg8SOfwj3GgSsdTmZJ2xEMRN3BqF9Hu8g==","Fdu2XF7GIWeGejgqiMdKZEYG2lZCVBplX6Y2P8VPziAZVnc9PXvl7scLZ7/n0TkaBqLKOgruKPQyQM3ZrfmSVg=="],"FileName":"testdata/cwtch.png","RootHash":"jw7XO7sw20W2p0CxJRyuApRfSOT5kUZNXzYHaFxF3NE2oyXasuX2QpzitxXmArILWxa/dDj7YjX+/pEq3O21/Q==","FileSizeInBytes":51791,"ChunkSizeInBytes":4096} \ No newline at end of file diff --git a/protocol/files/testdata/example.txt b/protocol/files/testdata/example.txt new file mode 100644 index 0000000..c57eff5 --- /dev/null +++ b/protocol/files/testdata/example.txt @@ -0,0 +1 @@ +Hello World! \ No newline at end of file diff --git a/protocol/model/peermessage.go.go b/protocol/model/peermessage.go.go new file mode 100644 index 0000000..6d3bfa2 --- /dev/null +++ b/protocol/model/peermessage.go.go @@ -0,0 +1,8 @@ +package model + +// PeerMessage is an encapsulation that can be used by higher level applications +type PeerMessage struct { + ID string // A unique Message ID (primarily used for acknowledgments) + Context string // A unique context identifier i.e. im.cwtch.chat + Data []byte // The serialized data packet. +} diff --git a/testing/cwtch.png b/testing/cwtch.png new file mode 100644 index 0000000000000000000000000000000000000000..e50812f7eb4da511c0964c3a9a061ee0ae140181 GIT binary patch literal 51791 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 z z=!a=--3WkM?$Q*Tfi`jbn#Jt$xZb_HNQ{+zu9cvjAsppb9JLU+i}?y??bhw>v8W=--o{|b-_>g1=WVn$cst?`s{OU)|z{h?( zb??9mA4c$a#W#Mlf$Di>y+dFq9kM39>2@V}q;fy+ovP<5b8kdh!BRlmJX zW&<_~t+&YJZCU?s-{cz|WB`M|FPnhObZEH6)aT{j&KpsBtDd32kp|Fo(kFgLov*=~ zj!(%Ho{UbAjl9R(PbFP-d_PB>$QvG&OyX9(E9^BH{Wge#7)~Z8vcDdV`^NjJqD(q9 zNh8<}`ihf(KP;jSOwG>^Tjr#pq4Vx398WSxoxIgyt|*km`s{G?h%W4(Kx(rfH0p>Z4pY_2hLhSO?T&B(a1a6`01qhY-yO2 zGkT)Ewx$YBVaa^cmaYrma>+2HHLND_C4J4rvZ(-!*|d7?NY@pfiDwP2J6+cKMBDbf zyN}+e^?jTd{P46W9VK0#WkMBP%H0n?*@XP=R(qY-f__bo^gFz*_aW*pr}tFrj?a5J z_UBJcfB!bTA*Q!pqwwEFDmY|GAvm$fO8~k2Gs>FYD9~C4a z1W58TOp>MtWY52Ru9Eo^p7rz7O;ec9VUF)v4FZ@2zsc zI1J;6;$*4pQ^1B6WhSN4RaI49ra!2usmJhi;e*QJWqVHfhht5OPh@fS{le3r=bEMVIUO!=`$VEt`yXX*BIHJ{Vwmd(OrY9kbo19YHX7pd#jscltS&rqE1S} z4Ni8HSgaCj)|WHo@ZAd605G6?XhTi6#Cn# zXWpM=mTqjQ{FeUIcD17B*(Ovzc2HoKfBT9y3>k4#DaV=F{P|+7TE=LJ>ScU>dlqS` zUumB1-*=@HPtTi5%(AYRau?(WT5u%n2)Xu;Qd#D8lnD(L6@KO)!x3Nh(`)>iJd>)) zh*b|e;3HxGvT(4vs%Tc?eQhlzI5kAbr}T~^8JNIK!P12r-T^Xl_pXnAkM>6tmV=|e zew7>E5J)9eefaQ!uF9tHqn$S{u@uzfS1ld2arnwp3aGqDyH!P79xz6P(sGEI?T^_l zFatD?DNud8?Kpn7|K>a1%75M}7nn1Frhx!CU+Y-M`SQe)eK66;6YqVn2H&AuUih-t z`ZkWY%iwUl&)j-nUy#{VPcWiZwDjR;W|E%a-#ZrUzdxy7due4{AWIe(4l<*-_~9AT zYq-`B)oUo!$F|S-r5`#8yYFvRLgh!rFHV-a27j1*eaS28@hL1sAOWo@55KYz109cM z|AW!CL`*3^621?OEeYk>j2WJfbE^NPc%O{)aq{Jh9DR;Jmq6SBr8jIB7DS@>tBBXH zr%>peuYL@c(I7TLRox9H^ZM{ThPi3`@tPqQSrYjW17l+W&`%Rj@A=15h}T29`kXod z8|HNg%kE>=6fE_p%q-Y!!1<_wW*I8~knH|~3z0PfYJco(Y^sjkG-E#>cTR$oBqGUD zFZ-`YO8kmZEY!7F3z#@PuSQEgH$R`}I{x^oB5jPMEj|LDmbx2s66iS}K54i`c~A;% zcmUo)^j)59>SAJI*Tz1n$}43ZG53{#?hE{4^YZ((i@FK&%-Pwg0O85w#@5IN5U2U= z-Qj?vSvr_rMlEPqV^%KtlcArk5GSdY@BG$%ZF6t}W`f_H%$J!|9wXV(ra5Y_`VFjP zwCgRNzBR4(tzv^s!xn}E1VWE<(g+%(B?N2=i?5=(pz7b1716dtWn|YstIZd~Mh!LK zK7nJxfoY1H2R2s5CD2K`*mP8W`>y0HYE8Etn|;&=`E&*)4(}QL;YOmomWwjYaAKJF zd+>>f_GdAYFF6u20Hv<@fGe3s^zdLH_Q@;2Bh4s7pDfFCRpiFRCN-UTfUceqpuou* z&~KRECrkGR)xaL+CrAF+Q0B)n#f!_{cNRD5@{Kp^`uf5evm+#uRyWq~_)ARCQ;;Gu zo(m`~WIQM-QGi)Tz5{W2s)b*QYv{>~mBj`0Q0N0MFHk^7w~6HmT>)d~bWpqUJU5TL zNHE6Wb3{p)Ne~lx)z7-)0b?A2>O{u0g@w`gV=2d?XhyB;!CNcvwpf;2KMN<{bzy66 zk)TuZV#jO&z(=w3)Mp%TPwNf4fi;=5Tl&`=7$p3o-QXGd1-FFxoeo)hH zK})H6JRdioLddi&>c|sx#0{mr2a4y6b!s$8N%EmpvVsu-?PMx&V+~#Um#*(aG_p=N zm_B715??zkW;Q%D)W58(%%Kz&;44h5sm|o0 zd!pC}6y<5t*mW;7m(5BH^&MUw_v@(s`jrh41PM)!VJosEJJQHsu2e-7x6wHUcc=qf z9VjrCS|ZOV&t1CY!58rFl1^XGS8rWGC|EU;ZuPTF#99%qWx@!Jm+c|3$g7ZOO5L72 z-}%Qq>II|+wDdh&wX{_CpEM4-TDMFwQ11F9yg$Y6ydlC`>1VPZ@{mx_Yq`k3kxr*? zEpiP&PoL0C13lZz8k0A-ViLA1JVM?$EC3w+ah6y!Kc$P% zV>W<(sW3xdb>cWR^Qlv(h{O`Bgr+B-Iy(G;?3B7qo=~qmaQ9*>9|?2eb+bnEH);Ch zBuiHJP4R;y&>z>Yjxb0|UpXm&f2RMa3!gSz=EC-0IgbuAC{cn`z;&(PQuTU&OfP7ND^3XfuQETcau7YW4 zKDXTNpVrNKMn>ZIJEeJIF*-eMW^rLt3c3h#azA!TC=jp{ZFjBk8d_ZR*n+!u`4M^` z1v7!LvDe_y5Nqm(Jh=$DVQlGB4#RN6(k=moAa=yyAOyuQCeFN8@+4^=9}*`Gd~w|C zYbHx#YGmOTHy6#%Z)BqA$zE_MH(;wW2NwKHiN22s85F4#`4uPIwB zcvRk543qBG1p@YBTZ4kjNY(rIz5yEtI-jH?Y2~o}S9pq1*ak z-Ujud^YuQ=0$7XFUB0PT*t%J%{o+8Y!}u7j-R@j9HY$?Otv}Aow)75eZ<2gS@8~~( z7s$QxBXMbcvETjkqO6aP&-7?wjoE~u$?u#drBOKUg&XY|uzLZWD@$Q@hb!c&owJ>4 znXVg&LeY<*;V~MYNe3Fb%{4r=@7S~{WT1erwzy{@XFMCX7G!R$HX|BW=bSI6}ZlK z<$qe<{``xjMLWu5{5BK5tzP7?v>mwE$t(0^9@e-4K>}N@odFy^H zI`?e%UtUU>;i8n6m$&JES1EtzyKOUk6VQU*PwHGj#xy0QB0f8^S~xIC5q4;Z2h@6^ zJPApnl)W&q+UjfA|IK2r&elPfCuMPDwg27j@0JV9aeSn5kEczsmoRr?)NmHI=501) zBJx`y>JHr2SPWhgs=57Kqt=}xMb3k2)rB9gd7s{2kAg_mA&dkxDQq=F)Jkjy?^#zw z&x$)WK><(~pf33JwfPh2Wp3^q`N-E>g6|#Zjsx7(Yw+pDl*Jf!smQ(3?bNh z_0`<`cYSFz(S%MHRe&x>5&>QP@{>Z9h4HTNg1xm%2(rt&w|W!Ou}5-LDi@dru)-DA zFQ&rOOYJ{$a`}UMFg_u6T{L_fN0H=aH-Htl9(hYbx)iaG4d$8d08R4 zjT)J;$d1^br(1>bM(TFKzM&KaR#sM+(vC94e}ZP%7ocp?bHB28)@LQ<8+1)U^czQb8+H#^A1gh68LF!|Q<63fW1i9{Z{Y`PkDVOSV;)aC=-^{)MZ*QU+(oz& ztw&~N?GItnbFzo4_4QEqojQF$^DNL-XaN)=PZ~t^_#eDm?a0K$#}^Ly^u7+^;s1ss z+LZ8h1QS7b5oeR&38M1aK$QoYU;O$&fFYWxPf+Odk>|)ms-ri>D%EraS+kE3vD#N6-t#ry9_6 z*Pxi+!Xvk(yZhH$yT=CTg<$+)0>Z;j7?SueU|hxEM|)KfAL|ZMi5oNT{?C{aWKuj1 zd76qrl$yX@Bplaeu7Q$3teotq?&GXDFBI+KvT(u%HNA28jmEKP1j*iK+`w%4lHVr- zg3{{mcd~8nuMzPQ_yQcYUWw12JIwuCRl4$HW$_LxH#ebf7u>ryHoLyvRX(ebrq+b_FLwpyPO z6e?LX{_rr9kJRXp{{X$|P8hoqicElBY$2NKbj5G?Lx;SeNdp_t`0QEa!}xtg=jW7( z^c13Bfyb@6wA<#11QW65GV0i66Z zvujSjYw>;>?rRt{ZE_`r6iu6-1Ny%Rx0E?x--Uvi^;Sn=%>PGVs;NOjc^v6h=9zaS5TA3fNGc%6&Z9OZJ)P$2 zqyld8QvL)U6d`mg=#vQHH?{&yEj)X_+PZiWpU2zVn}BH9Wg@%zu8BQn+j zxS+hK!8;21NnrQ16rf&Bu)iK_dA$2(2ze<`Wo9m}s%5EO?1KwD8MUVTrKYCH5d5xC zQH`lBvB_jV2-isluUm-;y23+ij1}nKB@Z0nXy%K6S7A3Tb{49QUHk1-dm@~a@;-V8XCZMrX&sU66%UV^5>W;1o-(MelCPXYv;3PtnRU8gQKH+ zqPD2$>gY5pYH&&^Zjq9ey?WGu-zshu)HRZf6K45TkvxKZ+yUQCpJSg=OWse5^-M?q z^;mBu2bD#9UR<#J0s^Xgmw|~l;8vr2qmqdfXVyKpe}W1nigHtAg{1q8!xjbr9b|edUTh46dae7#~iVBk4E?*R;F5q9V&Au~raJ1^2Z3`dLV=`9($PAxAK7R#;tGv1@t! zIwTw7!1)ZzGC4@+M_$k_;v%MHU>LFh##zA<`0J{MsT5;i;}h!5M5KMprf7jjLKmtI zOvC+igK*+a8kkmT5pGb24WrzP^G`m*QwDJfJz^pTYmB17Db@ffcK^M_)(8Cjqus$$ z*MDi_PCamd{@&_F>z{#F1oT$r<(*LU^MEbVdx#{b=^rd-d&}J!AO_MhG2uuZ$91X< ziahtSIsa82?QOh@wZS{@_c~l>PNjH-YwY*)7Zndl8Lu86+t18$odYuK@-ZDK-vGNs z$F+#D!G!SXU4;+;M-fZz9MDqOVu`<1UCYpYL>N~Tyl&Q)&I+k^YgWS4jk-esG*NpE zx!bPlb3p6}fLthGp&V2;a$2~3w2R1JT#c))R>dNzl|Qn0`g}wOR(NsG)uS(d{`~nV zwLzkM%udDNSQAYoqHg@Rk!xy^HYF(k(t7dbWO+S$w9WbY^`9C~pbAlRoA85LLBx3f z9!eb7hYyq1;%#8MXJX1_$K}WtH5-om6hH3tpJ>UOmkH1Yws9tgaP)tE5TjpL?8F`q zv?VT*k{PsUYg^|elhIoei6{8Jw00v$Jv@#;@_?|Ai$<@_=HGZin!JJcyash!p?_&n z>SE^-{W)@euS&EfMbahufrqxc8XI5yHiENI{_G>%77zokUr$|~@yg4SLPF64pt;Fb z6}O*%T;7JK*MLtK5gB>3hmG{&vWAC;2SI8XD4mbHkJ%Pu?Pwkl!He*jjqTQN$*yhBBJ4+eH+*~MvzI~tNOgaZ)CPe4uzYVvzSbr?O+wtLp z5xsu)OYT~6bOqSAcfKp^sg;E=7j#9ViDiJacp94pl@C7E1AYx85s)YcECZVQSJz3{ z$bR!f{6TA`;}^ZY7!_Am@|E7)ZO(}_SHe+%RxH@<2eJ&2JBOqm1?J1FuS|1x5}E z6aQpUm?DWPulRda6$x;e7j%0$w_AF$qPP=;90+j}lC@HC;o6U8s;&y_)zpcDd|@_QitvhItb zrz}A}`S|*}FVaB4gFFwO^zlE@zx0kZJ$R|xx=FVC011^S3RKELvZ;#Zv^)ZnCWJ@k zVk+Fw3}ITfhO02JAsh{1stl$!VxGmqW*_e1RjIREPsGAkWJn0dyYpiU_d36P6dmmk zK7j7$>mm3Ah%AuO8^6g>?Cow6`CyFOzY&+LPX-;yYqYJM%M!iwpTS?h{D5sST`;tK zdr4vEA$|F4PY#OEH=tAGKB-|S+GSqp;oHZi!DrmJ{|Yz+XgYS~t^YwPVJ)s$2r_lm zD@Dh~$L&#kl3~kIitE;=;WA)!b?|WTiWYB%l#9F=n znr?!gp5op;UtQ8Kwe^!kVAa+g-%h@gfN8aXun&OCSD%yCfO4<9n;VEW+lO7164OvS z5$>zG8-sVB{f~cs2g)%2-_>wF<@=B{=D+bj<9iA)DJ9iqE%aRhJwyy4Y8LI^>NN$F zLPadYCBUa8$mQWgaKoOo&3%5gb#)U)Bh)Wug`q<8J-@vsvzc5U7&mN=*m3>v zhv^)Ixb}VJ%eUYU@gH&?zV7Ak}!}~ zLFp7|w5#jY8CF(dU9X(U?L?d~X8rQ-Nn2O~37wlW7PkOpp!v^*3V*9t1}|1WRw1^Q zvYouiFW;oN)b+Uepf zSWp}O1jsU?2(+N2H&A+~VueJb_>}p|#FQJPhw<^|c2}-g@u*xpJ30L5i?luc<(`MK z$4yN+A*CDZnsoal6AIO;{5DEBdEoln2FEia1ILF4uwpR8A4L9Xp4YG9>C8w?Z`6^RM~{3sRb03WWUf-651Rb7SG87dA#xAXggx@h!? z&a6dC=?HDnguVxxIFD#$iCyIIeexliBM)9xoSgd|%kyVlHY_cWJn7AAp%U}qv!m8r10zn{;;V?+J2O)y%$fx$u5uhh!Qo=dBdtA}JemOU@Ly2gza zh}GS11falp^yPT{F9@m_=l*@?1dpMDn4i;;S>mvj5%9YT#q}O>+=yn~WkwTEa|;VA zjy_N17px!;Dw<^kvp0s;-hrEM-<+5(vi;dyd)&ecN88hFCS zFdD`_m~NR6eYEFtGw1Y7oF8J!S=vvcUSdaKQj(3GoO3m>3P}WXrpUcIo#)dyYPR#~ zW;$ZJ2B9B8KBpX}+z=?~>g)X3MU7N&?GTm$c?DNZ{GXHuLuJIpx56D$1&=&1PpXW@ zrKQs}(Gy0-FJ8a?ClaUm@a3Y*F}!4$Z3R>lJw2g>foqH~7@C*}LvKC3@Q)`z-4606 zI{23|jI)HDI`^+zP_GB zaqJ{dLhu1(i!NW%?ov7F-o5)*j`#v+f1e*%qa?W+MOW`8ER#1UdR1>I#y<8`z)+9v zNR9Htc#kEKnsn&i3LC2MuWyP~2=j#kDBy4aULjCOSPkzN%WWG>nEn7zt1FKZ>KLRe zw7Oo1n=L}_3WA5IqHpfegN+ofmE8p%o8d`T(NS#X(!A@ddv!R;9#6wD6q}h@5|g6x zcF)kh|4U;S`<(hfGp)IW0hBIAItEWq&w8z$#AFZ6r<6mZjl7Z)blV((fz3Ix=X5|} z!k4S{_l{t+j=QJy?mB=v5eW$)7~h%b$khdzJyx3N(4-{19d~+KIWmhOi-=hwu&v9@ zrpY4vkLl``r!6&0q+SQ|VVq@l==p^ZUoSIqWntul;&5v$PP7sd-IE_3{$?8Y1F<(w1Nw}3N&a;v2(rbx zbLY}DNxKvBS5LwzrHN(WAe*Q@YtD%AN9({ss!5EFh@=gfbh&m-6$H5BXt)Ix*?-d3 zvVec;$hh%A=nFiz>gvkJ&~7s!ToNNG3tcO$eV+<1a-utm=(s7T=d#graI+0tw2&&n z>Nl~bYA~gzt*t-)QT3nG4n*BDcm>h$_j11>A;RrG<~N2?$=pLkuNxm2w9|1UI{zwK)}&G zUi~$N>E`1eWo14HJ3IVbCznZ=S&<5q8OBt2^lG5`si{pfQvSs+Y!4%*x8rgl^b-gH z-vRXM=42n^$+ly+=Krt{trBB5FgfUSMamz)*7bs72CQ)8q4og?!5D&Ha$g9S>>LtZPPjP4eXkQj=r zJwzjN_*eyJ(GjjTWW&_M764s!{n8PTfY8*_N;|gd@0~a2pgeSk!xwg=`b7gaVzK-C z?pWQSW_)>+0B?k`sLwIP!l{xHOTuwL<1KP;SL%gU>(!A>1>zM^xE_^c^04K>vo+vL zN|&_l{yhgqaiB|&rx zz{Wsq9ggzf9MyPiHQ(=qncX&i@pbtmTdnTx92=X1;af}f zWC{xld{U4eF`K+PooVD>35zIHCtl%gqWI)_cER}#WNnG*gE;Z!lR^Kn1=JGn9c7-v z4uVFFnSq>$CPI(EbuWu)-vbK`ZWo^?T@JmK zIlVhYU{?eLOADg2lkZP6H5mx-qp(r;aMPwi-i<&8^CX^Hzhi1@0!>({V;4op6vy`@?_`waX6chu=u`l+1&hM+nTZ_q-|ezN$fa$JE~x> zj@s4Z+5xlnhJxb{E~8)T648;_p>p=^Sr-i*9YUtCm50at^qG#`m&1}!ppui5(HBz) z2qcS$i=Vrj0~7;?6>*&p(6~CEOU+kRF*1^oP$dDz!{Uvw9iIzm7~OF#5id0^zVgYf z;E3x^Dz8Hd-!_2J`Faj6U1CbAF*6CK>nW)GgLl^+Q5Hnob-^&o@3ygp#aAUnX}^f5 zwDz4RVQ*1-_hM=0sOD!XhV3>wrf*#~JvDhOyE9-dAuAjYSZrjk3s_N@Yf{~9d zEyBP}B-`MYs6B4*L{yd3)j)=>1xfhZ9A{dTP!UwIqy|!`#l8X$jks)op56bhQgPVu;iHq02G(LjUl~C zUTka$uh)Hx#?ePuN-+d;A6OWbXwi}99|dYq&@gV3!w)=wS5c?G9~~vw#2Q2+-5dIq z)O?L(s_F&E07&SWC#$coZEjHLv;EKh=xX}fj2#LS!dlroPUPN1MfvSK>@gx^p8O%! zll$}MMFbPs0waUAQ?vh_B??>A>c0FQMic*-}jKVX+ z&J13RuzuKmgZ8g7P=&ZC!A4g@vLfHTT*WG(F8EmjCGx|mBRVx_Nc<7n^!T`fWKLY9 z(0zHp4FduKYB6ggHS0c{E-c^eTVLqNAetckN;WC87RQ@dM3T zZeYHc&m|7(E8pMpA~na@JnZo%%g&u)7=u%fMGBXX-@LH~U2Fusqa_eGRwz455v1}^VK!$6u5$tlYjY= z-Z4;MCJw{po^`j9W0?R((F6J-7CYxQoO1+J_Qvt(uZ3V_65tUa9KlLb(#BC$)Vy^Q zv!lB&zM%bNUnPDxxQ#2WOLNNtW<)Jehgl~pk(=)P_7)b_p|>uXzO#Q`VVJT0*yj12 zN`*Ju^%@bE3?A4E$2Juv&IFS}mt&fm)Id_Cuw)#=m_=sEdh^t4DgvQJJi)7DhwHY} z=(TU=wB;E(-IXD#homU|U1&%M1Q6zlLh1V!@|)p%#lTo_D2ekzuo4W^rU@@J zWYO^AalrjY)A!~Yo(2(b41>$C)sut-FzghC3wjx+rqV@a^n_qb)C${CH$Ak6Sg->% z6N87#OISRR7B~3sAEW0c3A4|IUEVGBy0leK4~1RT%D(!SZS>D;>|h9+EVx;5IB+7# z7!&3J`{olQRkQg_f2^Y>hFPq+{M_+M#ok^B69GX?+2fjo(AB44KL`~p6ROR%J^JFT z^Mc4AdXa%{$M5}eOQ`V03OhX{i@8Ju%_2=teOgRYNy9DL1rRikZZ98UtbMs(K-^ocy zpNyFUSyON|VLgK0!9g-{v9z+;R_@%>Jx3J8f#_p5#a-w$~1uIIW^KCKzD zJ=!}Y#Gv?hnra;1HzO;nFyQ_ISoN~HFkC!a^X{#4z2x^xa+_LNTV?qI^n}}6NRcjr z!J1pBDS*O7z@!#`^~6!^HEm%aH#RoFvJ-G__>BB}94ig?%rp%g(@=47k;Y4;wP*F1 z9DbC$Q`MCgZ^v2<&b>kZ{Na*Y&_>^#$vOrJ`L~ir;l7(41U_=%LgrY%CuwEzq#EMg zEUo;W9=^jtq$r~^@<(ku^j(o7=ME$9@}Gft2n(le&W8`@e0&shb940#4C1_J#cnC3fHW3J&YmA}QR(PHIB>t%!TSjW?(hbYt`;xX*dRoLldl^m=s_|`TC~$$51KE-wlgc;> zp6?i2T#3E#4D-qE42%FR``LnkhWLCc8SXez@e#OQwcC>gc4W=_JB)+E*H_BFPfo6E z!kBD3qq!%utH7_I6&Sm{^Zv>?XHZnpM&`stLis&=`bS2ndlV(f6ldezse;zJD|3p9 zB3f zv%o63%hhYwrk=0V?_KG*pGv{B$5mTPlEWgc9=Df|M>j)If05o%k7i&};4 z5DK3pC+E(mfE;-}3Dg63wlRmFZb~Unl9C{VjR+imop^ts6A?T%FmSg1<43}1t?tni z1yJawbPoaBr&lqzv;7G5vsaItdii3IEUVny=`QI8lA54ma0DpO^6Kg7!OW}cS`A6G z8tQ(S^v`U{2wI%6t!lL?rVbfyki1TdAdtFS1Vb5SA{u>50Xg#qc@iFtOkawNiz8XO zEmzGjfE|U?kULN;U|gX8&ue+G8qLWs13w~b?)^{Py&J2mTvnh*bqXEj_M=@u*~9uh zFjRXHC1YRqELA@X&Wr2fFy;+DRE6(W@;HED+Jkn?EG}M69+qhX0AS^%JK=Hs3~w#x zjDZAuR{+io;roh|sRZxd^;TDJ6tl8wFhq*+_fe~&3M}dtAHciRx0VkYWrO*>Fp1GP zi9vwX=C)Q-(Q`~NJ=T?xnvf#A_KNu8E{LS6!<11#t+>_y;{ufSJMD+bI*|2Q`SNE; zijhT%!ziH8sZ&Qm1}1qUU{Eg<+A+g9IfN?7J38(8Zntlz!z%XK7}qwTKoD5QwcQRk zY!$-Ek-2RYzNO$Av$_Q+=;BEXML0PX!B#dL`dZQg;^>Pv?ph)Uw%eg=rT zH)2uA>y9#goo$I+aEYRUOs~NC7la@zH%iOP+h#j{}2wPtPeVC-ZvxLl(ikyv6H=D z9lYa~B;vhN$dK)y^ba<)-V}3MSCSE)rA0Y~Mk50+Nph>;kkJYm<7iOt;Q(`)QY>Fy z_k9qaK4%?!3y|96b?vuR2%*|I?{_aCvOakxnDJc1$-WfF00u^dKT{LP(}boJbEpMP z?Ho#@&?BJ|Ogrb6=>Z3kQ1gILgBqQTuNOdMlJ8nZ{N*fCL2xKY99;q^4U@&7TQ3sb$Lufd4f+LnM)1H2Lxg$P3Kn5|Ln>K#cw#{AnZ9ydjsf6}*TPr}qZ^?ic_4@Y zhbS8khaPoth8|~I`^fFQ)nJI)7&g4x2@{l-^K0#yolHJGN% zzxj!ho}PZVt}rW$3`&x!)ixeWwvA+v0f2#(ThCvh7t@G`{6*f{W) z76ZQ-QkGj-c-FNP_mVrV?Fgca>bu~3!pldxep~qRyAgo{E;iKL7p3s{fGI%oih_gE zAY~XonGplBF2XW0A4O#OjR@|-x54_f5TUYlE zXr5E2bcf$?|MWZ1mLxn)7Z6abe80}Z->T)*3nT>9c!WLX_v0lQb3!znl;Csn!Pv;? z4{SRJuXuCh2r4q*s8Bk{eHRaA<5jo6ivQBbUN~y%TC{>Pj7m3upL!6Av%y4$4 zM$1avaqb?4ypD9C=iKQo4uV}t-TFYxHP-CzMWSZDQ4BJar)46OWL-O3vDj#(15%J>nP*xK`v~Asfo$yMevxwrSGOTNZ$N6*t=}z z=60Ta)4#1`o6l+e1PScw`R$tSKkW$`bSifx;R*5s)nv<}#=r`usp|KZYn3>r;5`V* z$S?sBOlon<9Dc%>NpA!^>=q?2h6&=yT5$l1Q~#yqxc8};YL+F zm978cqO|giPfNPamvZWki_(p1I3EWgC{%K;ouSF3wT+}?yL2Av8CBT1S%X&E@~Cv( zUsH?-tew{G*1vmq!lUO&y4v}R;l`AqC`HBZkhZXlCivL~#QrRb{`@DYTa#FU zb2({ua)5<O{Bt z9f!KTW%OsOR_EKdn|^gvzJB}mSMu=o-rmewZ>8|rvldP-qoZkn|I6T8JDiVZiGu>R z2d5JHAlT5<)E`g$66S!6+Lq#SU6jVIq;zk(UA*|^9ulogWlQ%7wcXJ(8#ah6WIj7B z0K`XZJO91>3$A^i)q5c>PCxyA7=MkG;?}L7Bj9ADSX4ZQ&&kUJZ7thJ4$#M?g_)VR z@8cfyAXUg#pivEbqj3*T9C#}UP^Q-3fhC#?2gggk%PXTd1NH8|&B>Vy!@2a7nRgoq zi-~yI_Q;Wbf?5H zdpOn4dmg-Kx8kH`_!CmWzJe@M5vZJ!X9pa4)4V)f&19OlPHSsvaZ0kU@fkb!*8-%F zJuH^0K8TZgo|H6FS#9bY0E2of(!6ED~Hm&;ZgY;K&T z8)QzM`rvJAYruvGoHOHfkl`eaF#vc{m9J;cIhSrncUS<1D-Y)fSHf~{-g8M&xP9!0 z|BTP;Gtfi>&o3FM9V$YK{Us?wZR-B6i2#I2J6k6(dsfG&|Em7umNUDkIa<$|i+qg* zv9h$Y`+`_^s0kR@Sy`XcEc7m3LuEbyp6;X5N~5-17yiLAwSD7HJnT5H>`00Ao8`T% z&x9bk(Ufi17(Y_B`SW45j9R&{X_OvhA2W=NHo}^$mFOFJwr?8kIYinO|R)un9|SI zJ(9h7bc%PjbBm}^-O$i<$!~31A2oIS^1E#eYCiyX2AKk$cQX`2kIM8kvG+KYTtop$ zW;pzB@l?5UNe~$a^+EsT>e(=do#_~9!ia4GExuVlb>?{9cZp4&6E*72NL_n($q^(m z{Q-d7=B9ffb!J+(?HW;-t%&lf8icK#5mZ8>sHk{;4cda4-j2cfwYGHe_^+Dd{A|dN znG-mem;nvD?X@3(kgEhqvY|#V>FKos&E+k_VRdzY|MpL9Uhe$|x)_m+AmPn*H8Af1 zyim(Y;L639d|0PY8bq3jhi8ms>Q;$2()i^G*XKQ;lV%$X8!%_moA50SGLx<{_c~%! z)o|gGKoH?I!Ed8ImP@iM_+%JR0>=f>=^70Rao! zEcVLw_9G^~5mt`{)Cx42x3V#789*BLp+77bDw>@7tbu{SGid-`w4DUvZRk#S_NceK zA#0=+rD=(;Vc=FVTvBO)co?+Wn#gwta@k>SFjBPb}SZcgdQzF+1ITL>q3%KyE&;B1WO56s*-lUgI6@U46}N7?R)p3Jf=rlgxZ5aYJpb;blb+qX#%W zv%&+2@2A6ZWRf*DZ{WvHBkEyGyb!gcqNd%%mVD7rBK{mu`aoT!7Rb48x%!oO2Vjo4 zKYtt&D*~$3f_E=kimzIoRfdfjv&5<)0bZS{4Gkg6cL|ecl$4C;sKx;7edIE99tbMy zGTXIYqr^)PwSZwB*)`^xElLASQ}O&@N2n5l^Pw+sQGhej)VJ1>V}%$~w?~By-fN-n zGbC3&0Ul<%Q_>4PL@z+6Ifj%F=*dyLP98Nx{FUL4^3Gn8#&IE}3jZ~JWvue5)1D!D znVxiLgE+i*N8+KyYkYgl+#AF?cH?E*gGfyZY=i-8@DegoTRGDEbU(;*u%sY|x~c}W zLnLnQD}l*%wms7sd`LE6Mjkzn$^}?h#PeMpJ$fG6I||ysHvGB%SC^Mx%8hagxM2)w zhqE+>g|oN_)^bai%yl?O}y zxJeEh@uI+fxhcU8sX0tTzJL-uD#z3Hyee9v`}f^t)LotL;-sUzwH{4b@fkLNS^m>OTn3=babq{d(-6qy(Ph9!Umh4eE+v^qWP}c{<_REz>bwL|25%v zSisHGdhk`Y?X6VqzB@x79X0}PXf5iVRmZtl+1Gvw(ZWQxj=>mgEZvUZVF~-brJlEU zOy8y^JLeVak|RvT@VxwU*U8lNTMm=B=ytbdH@^v6ug~cZP!U1FZ+`GFk!2_Khg;>F zY)zL3KdF2A|3M#N))mM|)ezJi?>Np-GKPm4psbIZK4o`CXQHuCq=Uz|Ca|l#&y_5a zY(7B&KsRHv!2;TKaJPMZg7At(Y1okTcp4<3-P!&mf`!uKmh0C1nY8M}>nAn@yT^e75@U`3_p8#q`$f+m zKZZZS7u+ywPxYTw#HuMxfvqyxfNB(e0ds+-`jsp3Wpn@{`QyunVa{TnFbsYk$>}?l zO~b<+!0`G!ih<#``@VN;m>hYjy5Tf=zdFIfEtUjv?ibpf!4P!Ymfh zHyT&sh%COhqKdmMNiAKI=@x0fKr9&laQup>1nUh1JYbFi`h9+HPPBlZ%Fx8b7KT;6 z^!ytDaV(6<5o z{uZF)!{OlC@PwEGMY(%`a5`D#HYN zjQ`(`ldF{t2NSPv+qQAu-|4clZhH8>DXA{>$2cCwiI*FQ_d)i@z)1ko2vG?M*3pPJ ztQ6W1Nl6I}g>q$x2promN=&^nvolM~$vg6J)LT`v5yn3~hAsVU7l(TJYJOPDOg-Yb z`B?2j)+|1_=(w;j*;TcjFv9(k5~XIhO4^lnW?ytyA_RB1cMbqYmFf8Ejv@#kQ=j*! z>FHacHq!lhQ1w*anG6Vcp0jE4)=DXSchI7u)W9X)#`P}GJAGyFYzHjlX5hRgIR(Yh zm04KxEI%Sb{dILiZHt~TRYF+i0Ode;vdoz1`@rPP$zf_Z-5PrwFn+AE&&pG;Bg|Q0?eti3mUz12WRX-054Gm#prHu$Bp*T{1KojILDCpI#wXK-`BMmVtrX4gH7WsEUvJu#$wl>3Se7u z2adHZ;PNCqqP05qBO%Yyj6DBFB?I(zFWj%6d8Q0uYkTeuk<_BhvQcT_+uUs6hRhAD z-BLjAFNILAJZoBO9HhS#Rs_Lp6wV!8Xi?jB_4F+OW}VCz>%E7sq@AqO3>y-jdZNwW zI(SvuV|)3PY`8Xm0QpMYvnasKX|Ldv;Axq$*FMzw7Yz)}?!4a7k<1(*gIjdo8l)id!a`(>9dMv^9M6jXVHv@~b zc)Qphoo0qWBAh!~M&GE3J7bO?uV#Tsuz`G-NEEHx`cXTO5my`CWZh_R^?;l7;2?kP zjGr0uI|L<+R*?NrG+Q4Q1CACn-jg?Gv0824^hz!O28)`~1b0&&B+$kG?W1lNhjS4>??OKYO@6bG>rI^>+{LA>h4_z$x#J3cBS?`{zf}&VQ9+ zXSS7MTBk=SSz1KkqCVRvOIR%2NU-Y?gMT%o(P00%NLXF%hf7u;Y>uts95ZZS5T@h} z;<3^+>7-x-wsv3(|E+8ilwL`$NXeTxHT$?Fa*Z2*-T5NlfiqRj2!7!n9#9_QFpIjF%BF# zkKOg#dV8+g@{J+@tC-==Mfy5XHgA@TOpy>ePKqlEzzV`waxA(MsIU^y8)1Zj+%*T|%EJXzA-5>4_H{7XFFHl`Ri^te^vH}wWyeOEHw=Az+i?r`5!x2Ao#s0K{ zJRc9i?-5l0r^%Q?gcDfI&CLnxgS36) z+;n^@hQ6r+o(=>70O;AJEFxjBj{a#m3?#VyYuLJwM||w1r2*~Z`+H-PnICjGsJw56 z8+rElD2iV!d!29o=qMq<6cn*#B{7lV zIJljTswxx3_iGC@i5Knjkz{|e=JK@sdnv546I6UiWh-gwNG$9M7B-F zXTgxvb%cg#@@8;#!{LVe_B5^Kr?4Z)6z__80Xu{vCP}jO>yU`Z=5}`X;UpesiGte6 zDH3s8G88h7Xg2YWb~-0Wn4(Sw2>G>LVC-(S^qa^YW1%Z@By4SM5&JWShlg#!Wr}3X z1G)>)O~&eKPQ2A&0VVJY(1~m4s~?5-8vohtDc-bCn^eeD?wyMgQc|K%`NEt?RilGk zYXOyvrff=Zi(Z)gv&XkGlX z+WfuBhR~1-zZ9_UI3P&T!5i?IKmQrJsh3~LQEW||zQHku8UFTds$%TjoaavgqylGi zD)}EY#S>E5%g)1t4wuzTJQ)(luSyaJt9eC+0TT;2pI{s*)V+R(9m1jaf}50}AVM1N z0Z>-&H2r6o3X}1eYE+`q`Q))N6_O40SP(>862TqF{`$tgygQV(uT4ys22n-5(lq z1FV#>V9X9l+M9Rp{%D5`7u@g*3tLx*5e}bEheM#@?y{3eg1!%e&#o@I~=QSS{R!9<@dX@;Mp`PL1FY=gfISOHtC6Ip~ zMIgRu%D9G7w=OnSqr4`FZZ9Vd;xL{i2==6Br(M$Q>h30WuhHvYF{-K)*}eO!=j`o| z|LF<7II4DxL2PwvE5yo|T3CP$A+J)PC8RDfxt@}gY=sH9kP^<=Dh9nhzss(!lJEs; z06|OMltszz3t=!;y@M$URW+ecIv<0uMItOQFL^BW>bSLG%Qzt zJ!|MY0K6x4?ftn>%uf3KN`8^#Qk=_gE!!_~$WuGV+qwY(X8^B@KFZS8+}^J3%Uk&p zmT3fk@+{%rp~5!N6e12_;W{u#d%>5Lir@pC0ejr3$oqYCNcF>A9)!d0z0*}+UnSD5 zaY)Un<+}AhZ20##H#1@$f_M{7pI6^qhVxL{mpV&Y;fVVE7KhR_Xl`oLVsF?x-tGk= z7c_Klf~-0}n5>k{RI$~ptt3H_2HQK-O%@+=^d8Pd%KRjnqMsufC5VB@yDEkaE%844nL4{`ahE)`%YV=(l za`Z<=q^de3^kM%KMxBcwV#Cc%r~pI%aI>-jJjS~j`0Rcyd^%7)2e+0UxDYZv-~X(W zvn{FnPg+SR(}8CUqhFS4O1JS3$Oxp6@UEWeNI->1uDadbl3>yBz5CR|K+>#D-Qg|| ziGvA@XujQKNGV}PXzMnCm<}NZbGRyY2rI{<^z^k6o0!%*Q(u~_tA@y9XJ~7Uy2@<# z*wG1AQ;e57#o9tqFxHm34KzU5P{%n29geT{eaUCK?cQ*5-)XR=dYtP=+#M_L+#=?Rlh{ zd`Y?II!bNGrnstkFG}N>7;>@pf3Rkuw%1>#I>KjK7+y}~)2ssK##AVyn!53j1HeRy zmF{w{WT4O@(WKJQ416DS5#;D|9gTB_e!c;Ff!9Hy6tn;H4DZ=FcIR6~4~aON;{BWO zq}&Y=CT-CZ2IGl{Ru_YpDkRmQC`$M$Ps_y2EQF5NRa8z08Q0HC_BFGR0!%1?SLG=`UmcB0+ z*b(p^C9VBG*F4~-Vq*CFBc7;`m{0a>`po8q7=uOneu zLnjct{v<{6?_Sgz98{A3IjH6!Rb-gss_@@$!RSVet|}2n`1^n`@;7;kd|S_d0Ip^0CW7lIGVy!0A7J3*X4Ir z5>-vcO+9daw*!q0sQ;3jr`__OqennzcBb)xJ23WQ#>Xu{n1WMJZ<)w>8rUzSIXZK5 zF`!QaaVk3?9EfTpEe0^7rttFGtX*3>fYwDVh*+seNlO=*`La)|!ArRklaRouZ&c5y z9=jxwrJ=1Y0@|X`;hYr|uLebIDBzsU+wpVF^CX<%X!?XeV z1Q4avZES=gN$msMhV9+mnzsj|qvoas#z9+_Y9z`ffP_%TRlRi$o^Ds3y=|OlWYzm9 za#G3|Q{(f1~_*md3ohFbxNgOF45t9bIUv{0HRIc{@U!Ma7gI9 z1utr9W+t?)O-n&RfmE53T2vsh3`37xq&dao$Fr3K{=WUSqGiCb3|XbkdVovz@X%?J1La@zyXOA#~mCTIG{$v(9}Zw4jE02CkCdjT13Go zU0~IH7dmxg$V*}PUHns-4Gohcz$Ht8^x{j{w%@8BT187IO? zVfd68xb^SA*^LLKbl#W!{5bvWNGoRstY)XNi^AmH2-7XdwwxCh7TS(%Taf+(?Ib(X z)ah50A;QPl5RDvIPBkxI{y`%Z*GZoq*#mebIX(N!Ay zLk&tXB$5@T7)~N;$=-IP56M$y_di|Dh%AO?pXw## z-+0@|-a95HMyUg?&jSx&K7T07$M>FYNSnGqWJ~j^PxR;A!Kth3kZnY!%K+<9wDFKG zGi6C8tg6opOKh_#4ibd7R4`{GktME_B3TLO0@2V&k)|;YSVIGzODxz)hho$EmuX>- zyZY&n{(_N_?fKYM6GWq{=lmC+FD9&;i-46%+ffPqy5mHT^h@TII~6oESP9#1D+Fo{DbD)0 z_x8>zj(&}(5`mX+0}TJ4ANy)N0NjZl-3F?n63B(X{!zON0O>c48hL(LNT@FGrtyf5cgXd24?k&l&CV{Mc{bo$!!9(_-pk+EHpnN_A9*)lB{5^)MaWk|ui{oc^G zZ*P$*u4}tT76h>q)Pfg%l@NM_!7Kg~GS(H)l@5(UIoxaNCl6?l^YvQ?jckm9QQkvV z`b_O-YEe_csIaE;m5yP#@MAq@M;moHFGNlBNT_%D@v8`)f=+93?9RF)T|bt)`%Fyz zdIK~4u#}7o>RJ9l}gD!7S+_5QL-DtSZ|~!H#e~G_3NJ&u-ns8S2Qx<`zmAj zO(r9wd!zWdrliqO@8i@{hq0?GjttM2v7M-IK}37KRB;Y21J_g@m*}ifL!*KvnEdHj rT3TW^o1_&AV>(a$|M`b+orua?wdJnY@dnd)1kusFqEUF>`r-cp0f?Qr literal 0 HcmV?d00001 diff --git a/testing/file_sharing_integration_test.go b/testing/file_sharing_integration_test.go new file mode 100644 index 0000000..305ba00 --- /dev/null +++ b/testing/file_sharing_integration_test.go @@ -0,0 +1,132 @@ +package testing + +import ( + "crypto/rand" + app2 "cwtch.im/cwtch/app" + "cwtch.im/cwtch/app/utils" + "cwtch.im/cwtch/event" + "cwtch.im/cwtch/functionality/filesharing" + "cwtch.im/cwtch/model" + "cwtch.im/cwtch/protocol/files" + "encoding/base64" + "encoding/hex" + "encoding/json" + "fmt" + "git.openprivacy.ca/openprivacy/connectivity/tor" + "git.openprivacy.ca/openprivacy/log" + mrand "math/rand" + "os" + "os/user" + "path" + "testing" + "time" +) + +func TestFileSharing(t *testing.T) { + + os.RemoveAll("cwtch.out.png") + os.RemoveAll("cwtch.out.png.manifest") + + log.SetLevel(log.LevelDebug) + + os.Mkdir("tordir", 0700) + dataDir := path.Join("tordir", "tor") + os.MkdirAll(dataDir, 0700) + + // we don't need real randomness for the port, just to avoid a possible conflict... + mrand.Seed(int64(time.Now().Nanosecond())) + socksPort := mrand.Intn(1000) + 9051 + controlPort := mrand.Intn(1000) + 9052 + + // generate a random password + key := make([]byte, 64) + _, err := rand.Read(key) + if err != nil { + panic(err) + } + + tor.NewTorrc().WithSocksPort(socksPort).WithOnionTrafficOnly().WithHashedPassword(base64.StdEncoding.EncodeToString(key)).WithControlPort(controlPort).Build("tordir/tor/torrc") + acn, err := tor.NewTorACNWithAuth("./tordir", path.Join("..", "tor"), controlPort, tor.HashedPasswordAuthenticator{Password: base64.StdEncoding.EncodeToString(key)}) + if err != nil { + t.Fatalf("Could not start Tor: %v", err) + } + + app := app2.NewApp(acn, "./storage") + + usr, _ := user.Current() + cwtchDir := path.Join(usr.HomeDir, ".cwtch") + os.Mkdir(cwtchDir, 0700) + os.RemoveAll(path.Join(cwtchDir, "testing")) + os.Mkdir(path.Join(cwtchDir, "testing"), 0700) + + fmt.Println("Creating Alice...") + app.CreatePeer("alice", "asdfasdf") + + fmt.Println("Creating Bob...") + app.CreatePeer("bob", "asdfasdf") + + alice := utils.WaitGetPeer(app, "alice") + bob := utils.WaitGetPeer(app, "bob") + + alice.AutoHandleEvents([]event.Type{event.PeerStateChange, event.NewRetValMessageFromPeer}) + bob.AutoHandleEvents([]event.Type{event.PeerStateChange, event.NewRetValMessageFromPeer, event.ManifestReceived}) + + queueOracle := event.NewQueue() + app.GetEventBus(bob.GetOnion()).Subscribe(event.FileDownloaded, queueOracle) + + app.LaunchPeers() + + waitTime := time.Duration(30) * time.Second + t.Logf("** Waiting for Alice, Bob to connect with onion network... (%v)\n", waitTime) + time.Sleep(waitTime) + + bob.AddContact("alice?", alice.GetOnion(), model.AuthApproved) + alice.PeerWithOnion(bob.GetOnion()) + + fmt.Println("Waiting for alice and Bob to peer...") + waitForPeerPeerConnection(t, alice, bob) + + fmt.Println("Alice and Bob are Connected!!") + + filesharingFunctionality, _ := filesharing.FunctionalityGate(map[string]bool{"filesharing": true}) + + err = filesharingFunctionality.ShareFile("cwtch.png", alice, bob.GetOnion()) + + if err != nil { + t.Fatalf("Error!") + } + + time.Sleep(time.Second * 10) + + for _, message := range bob.GetContact(alice.GetOnion()).Timeline.GetMessages() { + + var messageWrapper model.MessageWrapper + json.Unmarshal([]byte(message.Message), &messageWrapper) + + if messageWrapper.Overlay == model.OverlayFileSharing { + var fileMessageOverlay filesharing.OverlayMessage + err := json.Unmarshal([]byte(messageWrapper.Data), &fileMessageOverlay) + + if err == nil { + filesharingFunctionality.DownloadFile(bob, alice.GetOnion(), "cwtch.out.png", fmt.Sprintf("%x.%x", fileMessageOverlay.Hash, fileMessageOverlay.Nonce)) + } + } + + fmt.Printf("Found message from Alice: %v", message.Message) + } + + // Wait for the file downloaded event + ev := queueOracle.Next() + if ev.EventType != event.FileDownloaded { + t.Fatalf("Expected file download event") + } + + manifest, err := files.CreateManifest("cwtch.out.png") + if hex.EncodeToString(manifest.RootHash) != "8f0ed73bbb30db45b6a740b1251cae02945f48e4f991464d5f3607685c45dcd136a325dab2e5f6429ce2b715e602b20b5b16bf7438fb6235fefe912adcedb5fd" { + t.Fatalf("file hash does not match expected %x: ", manifest.RootHash) + } + + app.Shutdown() + acn.Close() + +} diff --git a/testing/tests.sh b/testing/tests.sh index fd268a8..8a3d9a7 100755 --- a/testing/tests.sh +++ b/testing/tests.sh @@ -9,6 +9,7 @@ go test -race ${1} -coverprofile=storage.v0.cover.out -v ./storage/v0 go test -race ${1} -coverprofile=storage.v1.cover.out -v ./storage/v1 go test -race ${1} -coverprofile=storage.cover.out -v ./storage go test -race ${1} -coverprofile=peer.connections.cover.out -v ./protocol/connections +go test -race ${1} -coverprofile=peer.filesharing.cover.out -v ./protocol/files go test -race ${1} -coverprofile=peer.cover.out -v ./peer echo "mode: set" > coverage.out && cat *.cover.out | grep -v mode: | sort -r | \ awk '{if($1 != last) {print $0;last=$1}}' >> coverage.out