Compare commits

...

35 Commits
linarm ... main

Author SHA1 Message Date
Dan Ballard 7a65efaa78 change to use new go-cross-compile container
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is pending Details
2024-03-05 09:38:14 -08:00
Sarah Jamie Lewis 83c84b2049
Add Reload Field to CwtchStarted event
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-02-26 18:01:46 -08:00
Sarah Jamie Lewis 6618410cc9
Upgrade Cwtch
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-02-26 09:28:36 -08:00
Sarah Jamie Lewis 89f19928c2
Load Correct Profile Image when ProfileImageExperiment is Disabled
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-02-23 15:22:12 -08:00
Sarah Jamie Lewis 243727a131 Fix Cwtch on Tails > 5.13
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-02-12 11:04:54 -08:00
Sarah Jamie Lewis dd0f1cd868 Upgrade Cwtch for eventbus dedupe fix
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2024-02-09 13:23:42 -08:00
Sarah Jamie Lewis 5bf954f3d0 Upgrade Cwtch
continuous-integration/drone/push Build is pending Details
continuous-integration/drone/pr Build is passing Details
2024-02-09 13:07:30 -08:00
Sarah Jamie Lewis 425c3e6030 Expose new Enhanced Permission APIs
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-15 10:14:52 -08:00
Sarah Jamie Lewis 32ea146ec0 Upgrade Cwtch 2024-01-15 10:07:19 -08:00
Sarah Jamie Lewis 6321f09aad Improve Quality Scripts and Fix nilaway issues. 2024-01-15 10:07:19 -08:00
Dan Ballard 9e3fc6123b fix building mac amd64 build on m1 arm machines
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-05 18:11:05 -08:00
Sarah Jamie Lewis cbe687ce2e Try out minimal version flags on Mac Builds
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-05 21:11:54 +00:00
Sarah Jamie Lewis 6c0b2e2a4f Explicitly Use Bullseye for Linux Builds
continuous-integration/drone/push Build is passing Details
2024-01-03 20:52:51 +00:00
Sarah Jamie Lewis 7c042334d3 Update '.drone.yml'
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2024-01-03 17:55:51 +00:00
Sarah Jamie Lewis c7c2259c2d More .drone updates
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is failing Details
2024-01-02 16:09:07 -08:00
Sarah Jamie Lewis c2c3c2894d Upgade Cwtch, Allow Unsigned APIs.
continuous-integration/drone/pr Build is failing Details
Also update .drone
2024-01-02 16:06:38 -08:00
Sarah Jamie Lewis 7ddf09caec Expose PublishServerInfo
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-26 13:15:16 -07:00
Sarah Jamie Lewis 41a554a198 Upgrade Cwtch
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-25 18:37:46 +00:00
Dan Ballard b80db89284 Remove auto loadProfiles with default password from StartCwtch. Leave for apps to do
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-24 09:56:37 -07:00
Sarah Jamie Lewis 20dc170a78 Upgrade Cwtch
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-19 17:02:09 -07:00
Sarah Jamie Lewis 267e79368e Upgrade Cwtch, Log Errors for Experiments
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-09-19 13:05:08 -07:00
Sarah Jamie Lewis f93616615a Upgrade Cwtch
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-09-18 08:09:50 -07:00
Sarah Jamie Lewis 3e9c9c3b70 Use Constant from Cwtch
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is passing Details
2023-09-13 11:52:11 -07:00
Sarah Jamie Lewis f60fbfc3d5 Upgrade Cwtch. Support Disconnection and Appearing Offline 2023-09-13 11:50:13 -07:00
Sarah Jamie Lewis f32ad741e0 Hashes
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is passing Details
2023-08-31 11:56:41 -07:00
Sarah Jamie Lewis a453ca9dc8 Update Cwtch
continuous-integration/drone/pr Build is running Details
2023-08-31 11:55:02 -07:00
Sarah Jamie Lewis 3d2124126b Update
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is passing Details
2023-08-22 14:06:27 -07:00
Sarah Jamie Lewis 0f40f0d12d Upgrade Cwtch Expose DeleteServerInfo
continuous-integration/drone/pr Build is failing Details
2023-08-22 13:27:09 -07:00
Sarah Jamie Lewis 6e0623170f Fix up Spec and Makefile
continuous-integration/drone/pr Build is running Details
continuous-integration/drone/push Build is passing Details
2023-08-02 13:12:53 -07:00
Sarah Jamie Lewis 6fdcf5bac7 Upgrade Cwtch
continuous-integration/drone/pr Build is pending Details
continuous-integration/drone/push Build is passing Details
2023-08-02 09:30:19 -07:00
Sarah Jamie Lewis ae18550f71 Upgrade Cwtch
continuous-integration/drone/pr Build is running Details
2023-07-27 11:09:54 -07:00
Sarah Jamie Lewis 988ec07ebc Correct Package name
continuous-integration/drone/pr Build is running Details
2023-07-25 14:54:59 -07:00
Sarah Jamie Lewis 44241e2352 Update Server Info
continuous-integration/drone/pr Build is running Details
2023-07-25 14:48:33 -07:00
Sarah Jamie Lewis 403398b7a1 Patch Makefile 2023-07-25 14:46:52 -07:00
Sarah Jamie Lewis 5916333723 Expose Search and new ServerList Functions 2023-07-25 14:46:09 -07:00
14 changed files with 224 additions and 224 deletions

View File

@ -5,15 +5,20 @@ name: linux-android-windows-test
steps:
- name: fetch
image: golang:1.19.1
image: openpriv/go-cross-compile:2024.02
volumes:
- name: deps
path: /go
commands:
- go install honnef.co/go/tools/cmd/staticcheck@latest
- wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/tor
- wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/torrc
- chmod a+x tor
- go install go.uber.org/nilaway/cmd/nilaway@latest
- wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/branch/master/tor/tor-0.4.8.9-linux-x86_64.tar.gz -O tor.tar.gz
- tar -xzf tor.tar.gz
- chmod a+x Tor/tor
- export PATH=$PWD/Tor/:$PATH
- export LD_LIBRARY_PATH=$PWD/Tor/
- tor --version
- export GO111MODULE=on
- git fetch --tags
- go mod download
- echo `git describe --tags` > VERSION
@ -21,7 +26,7 @@ steps:
- export GOSUMDB="off"
- name: build-linux
image: openpriv/golangxarm:1.19.1
image: openpriv/go-cross-compile:2024.02
volumes:
- name: deps
path: /go
@ -31,7 +36,7 @@ steps:
- make linux
- name: build-android
image: openpriv/android-go-mobile:2023.02
image: openpriv/go-cross-compile:2024.02
volumes:
- name: deps
path: /go
@ -44,7 +49,7 @@ steps:
- make android
- name: build-windows
image: openpriv/mingw-go:2023.01
image: openpriv/go-cross-compile:2024.02
environment:
GOPATH: /go
volumes:
@ -55,7 +60,7 @@ steps:
- make windows
- name: deploy-buildfiles
image: kroniak/ssh-client
image: openpriv/go-cross-compile:2024.02
pull: if-not-exists
environment:
BUILDFILES_KEY:
@ -146,7 +151,7 @@ steps:
status: [ success ]
commands:
- echo $BUILDFILES_KEY > ~/id_rsab64
- base64 -d ~/id_rsab64 > ~/id_rsa
- base64 -d -i ~/id_rsab64 -o ~/id_rsa
- chmod 400 ~/id_rsa
- export DIR=libCwtch-autobindings-`cat COMMIT_DATE`-`cat VERSION`
- mkdir -p $DIR

View File

@ -16,16 +16,16 @@ ifneq (,$(shell which $(ARM_X_CC)))
LINUX_X_ARM = libCwtch.x.so
endif
linux: EXPERIMENTS ?= serverExperiment
linux: EXPERIMENTS ?= "serverExperiment"
linux: libCwtch.so $(LINUX_X_ARM)
macos: EXPERIMENTS ?= serverExperiment
macos: EXPERIMENTS ?= "serverExperiment"
macos: libCwtch.x64.dylib libCwtch.arm64.dylib
android: EXPERIMENTS ?=
android: EXPERIMENTS ?= ""
android: cwtch.aar
windows: EXPERIMENTS ?= serverExperiment
windows: EXPERIMENTS ?= "serverExperiment"
windows: libCwtch.dll
@ -48,20 +48,20 @@ libCwtch.x.so: lib.go
./switch-ffi.sh
mkdir -p build/linux
ifeq ($(ARCH),x86_64)
env CGO_ENABLED=1 CC=$(ARM_X_CC) GOARCH=arm64 go build -trimpath -ldflags "-buildid=autobindings-v0.0.3-22-g20065b2 -X main.buildVer=autobindings-v0.0.3-22-g20065b2 -X main.buildDate=2023-05-01-21-41" -buildmode c-shared -o libCwtch.x.so
env CGO_ENABLED=1 CC=$(ARM_X_CC) GOARCH=arm64 go build -trimpath -ldflags "-buildid=autobindings-$(shell git describe --tags) -X main.buildVer=autobindings-$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.x.so
mv libCwtch.x.so build/linux/libCwtch.arm64.so
mv libCwtch.x.h build/linux/libCwtch.h
endif
libCwtch.x64.dylib: lib.go
./switch-ffi.sh
go build -trimpath -ldflags "-buildid=autobindings-$(shell git describe --tags) -X main.buildVer=autobindings-$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.x64.dylib
env CGO_CFLAGS="-mmacosx-version-min=10.12" CGO_LDFLAGS="-mmacosx-version-min=10.12" GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 go build -trimpath -ldflags "-buildid=autobindings-$(shell git describe --tags) -X main.buildVer=autobindings-$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.x64.dylib
mkdir -p build/macos
mv libCwtch.x64.dylib build/macos/
libCwtch.arm64.dylib: lib.go
./switch-ffi.sh
env GOARCH=arm64 GOOS=darwin CGO_ENABLED=1 go build -trimpath -ldflags "-buildid=$(shell git describe --tags) -X main.buildVer=$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.arm64.dylib
env CGO_CFLAGS="-mmacosx-version-min=10.12" CGO_LDFLAGS="-mmacosx-version-min=10.12" GOARCH=arm64 GOOS=darwin CGO_ENABLED=1 go build -trimpath -ldflags "-buildid=$(shell git describe --tags) -X main.buildVer=$(shell git describe --tags) -X main.buildDate=$(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)" -buildmode c-shared -o libCwtch.arm64.dylib
mkdir -p build/macos
mv libCwtch.arm64.dylib build/macos/

View File

@ -13,8 +13,5 @@ const PeerOnline = "peer-online"
const PeerAutostart = "autostart"
// Description is used on server contacts,
const Description = "description"
// ConversationNotificationPolicy is the attribute label for conversations. When App NotificationPolicy is OptIn a true value here opts in
const ConversationNotificationPolicy = "notification-policy"

View File

@ -1,4 +1,4 @@
package servers
package server_hosting
import (
"cwtch.im/cwtch/app"

View File

@ -1,66 +0,0 @@
package groups
import (
"cwtch.im/cwtch/event"
"cwtch.im/cwtch/model"
"cwtch.im/cwtch/model/attr"
constants2 "cwtch.im/cwtch/model/constants"
"cwtch.im/cwtch/peer"
"cwtch.im/cwtch/protocol/connections"
"fmt"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/constants"
)
const groupExperiment = "tapir-groups-experiment"
const (
// ServerList is a json encoded list of servers
ServerList = event.Field("ServerList")
)
const (
// UpdateServerInfo is an event containing a ProfileOnion and a ServerList
UpdateServerInfo = event.Type("UpdateServerInfo")
)
// GroupFunctionality provides experiment gated server functionality
type GroupFunctionality struct {
}
// ExperimentGate returns GroupFunctionality if the experiment is enabled, and an error otherwise.
func ExperimentGate(experimentMap map[string]bool) (*GroupFunctionality, error) {
if experimentMap[groupExperiment] {
return new(GroupFunctionality), nil
}
return nil, fmt.Errorf("gated by %v", groupExperiment)
}
// GetServerInfoList compiles all the information the UI might need regarding all servers..
func (gf *GroupFunctionality) GetServerInfoList(profile peer.CwtchPeer) []Server {
var servers []Server
for _, server := range profile.GetServers() {
servers = append(servers, gf.GetServerInfo(server, profile))
}
return servers
}
// GetServerInfo compiles all the information the UI might need regarding a particular server including any verified
// cryptographic keys
func (gf *GroupFunctionality) GetServerInfo(serverOnion string, profile peer.CwtchPeer) Server {
serverInfo, _ := profile.FetchConversationInfo(serverOnion)
keyTypes := []model.KeyType{model.KeyTypeServerOnion, model.KeyTypeTokenOnion, model.KeyTypePrivacyPass}
var serverKeys []ServerKey
for _, keyType := range keyTypes {
if key, has := serverInfo.GetAttribute(attr.PublicScope, attr.ServerKeyZone, string(keyType)); has {
serverKeys = append(serverKeys, ServerKey{Type: string(keyType), Key: key})
}
}
description, _ := serverInfo.GetAttribute(attr.LocalScope, attr.ServerZone, constants.Description)
startTimeStr := serverInfo.Attributes[attr.LocalScope.ConstructScopedZonedPath(attr.LegacyGroupZone.ConstructZonedPath(constants2.SyncPreLastMessageTime)).ToString()]
recentTimeStr := serverInfo.Attributes[attr.LocalScope.ConstructScopedZonedPath(attr.LegacyGroupZone.ConstructZonedPath(constants2.SyncMostRecentMessageTime)).ToString()]
syncStatus := SyncStatus{startTimeStr, recentTimeStr}
return Server{Onion: serverOnion, Identifier: serverInfo.ID, Status: connections.ConnectionStateName[profile.GetPeerState(serverInfo.Handle)], Keys: serverKeys, Description: description, SyncProgress: syncStatus}
}

View File

@ -1,23 +0,0 @@
package groups
import "testing"
func TestGroupFunctionality_IsEnabled(t *testing.T) {
_, err := ExperimentGate(map[string]bool{})
if err == nil {
t.Fatalf("group functionality should be disabled")
}
_, err = ExperimentGate(map[string]bool{groupExperiment: true})
if err != nil {
t.Fatalf("group functionality should be enabled")
}
_, err = ExperimentGate(map[string]bool{groupExperiment: false})
if err == nil {
t.Fatalf("group functionality should be disabled")
}
}

View File

@ -1,20 +0,0 @@
package groups
type ServerKey struct {
Type string `json:"type"`
Key string `json:"key"`
}
type SyncStatus struct {
StartTime string `json:"startTime"`
LastMessageTime string `json:"lastMessageTime"`
}
type Server struct {
Onion string `json:"onion"`
Identifier int `json:"identifier"`
Status string `json:"status"`
Description string `json:"description"`
Keys []ServerKey `json:"keys"`
SyncProgress SyncStatus `json:"syncProgress"`
}

View File

@ -96,7 +96,9 @@ func main() {
case "profile":
generatedBindings = generateProfileFunction(generatedBindings, fName, args)
case "(json)profile":
generatedBindings = generateJsonProfileFunction(generatedBindings, fName, args)
generatedBindings = generateJsonProfileFunction(generatedBindings, fName, args, false)
case "(json-err)profile":
generatedBindings = generateJsonProfileFunction(generatedBindings, fName, args, true)
case "@profile-experiment":
experiment := args[0]
generatedBindings = generateExperimentalProfileFunction(generatedBindings, experiment, fName, args[1:])
@ -146,6 +148,10 @@ func intArgPrototype(varName string) (string, string, string, string) {
return fmt.Sprintf(`%s C.int`, ToSnakeCase(varName)), fmt.Sprintf(`int(%v)`, ToSnakeCase(varName)), fmt.Sprintf(`%v int`, varName), varName
}
func uintArgPrototype(varName string) (string, string, string, string) {
return fmt.Sprintf(`%s C.uint`, ToSnakeCase(varName)), fmt.Sprintf(`int(%v)`, ToSnakeCase(varName)), fmt.Sprintf(`%v int`, varName), varName
}
func conversationArgPrototype(varName string) (string, string, string, string) {
return intArgPrototype(varName)
}
@ -235,7 +241,7 @@ func mapArgs(argsTypes []string) (string, string, string, string) {
gUse = append(gUse, c4)
case "int":
if len(argTypeParts) != 2 {
fmt.Printf("generic bool arg must have have e.g. bool:<name>\n")
fmt.Printf("generic int arg must have have e.g. int:<name>\n")
os.Exit(1)
}
c1, c2, c3, c4 := intArgPrototype(argTypeParts[1])
@ -243,6 +249,20 @@ func mapArgs(argsTypes []string) (string, string, string, string) {
c2GoArgs = append(c2GoArgs, c2)
goSpec = append(goSpec, c3)
gUse = append(gUse, c4)
case "uint":
if len(argTypeParts) != 2 {
fmt.Printf("generic uint arg must have have e.g. uint:<name>\n")
os.Exit(1)
}
c1, c2, c3, c4 := uintArgPrototype(argTypeParts[1])
cArgs = append(cArgs, c1)
c2GoArgs = append(c2GoArgs, c2)
goSpec = append(goSpec, c3)
// because of java/kotlin/android/gomobile inability to recognize unsigned integers
// we need to pretent this is a signed interface...so do the final cast here...
// this will cause bad behavior if a negative number is passed through the java
// interface...so...don't do that...
gUse = append(gUse, fmt.Sprintf("uint(%s)", c4))
case "string":
if len(argTypeParts) != 2 {
fmt.Printf("generic string arg must have have e.g. string:<name>\n")
@ -364,7 +384,7 @@ func {{FNAME}}({{GO_ARGS_SPEC}}) {
return bindings
}
func generateJsonProfileFunction(bindings string, name string, argsTypes []string) string {
func generateJsonProfileFunction(bindings string, name string, argsTypes []string, handleErr bool) string {
appPrototype := `
//export c_{{FNAME}}
func c_{{FNAME}}({{C_ARGS}}) *C.char {
@ -374,14 +394,26 @@ func c_{{FNAME}}({{C_ARGS}}) *C.char {
func {{FNAME}}({{GO_ARGS_SPEC}}) string {
cwtchProfile := application.GetPeer(profile)
if cwtchProfile != nil {
return cwtchProfile.{{LIBNAME}}({{GO_ARG}})
{{HANDLE_FUNC}}
}
return ""
}
`
noErrorPrototype := `return cwtchProfile.{{LIBNAME}}({{GO_ARG}})`
withErrorPrototype := `res,err := cwtchProfile.{{LIBNAME}}({{GO_ARG}})
if err != nil {
log.Errorf("could not {{FNAME}} %v", err)
}
return res`
functionPrototype := noErrorPrototype
if handleErr {
functionPrototype = withErrorPrototype
}
cArgs, c2GoArgs, goSpec, gUse := mapArgs(argsTypes)
appPrototype = strings.ReplaceAll(appPrototype, "{{HANDLE_FUNC}}", functionPrototype)
appPrototype = strings.ReplaceAll(appPrototype, "{{FNAME}}", strings.TrimPrefix(name, "Enhanced"))
appPrototype = strings.ReplaceAll(appPrototype, "{{LIBNAME}}", name)
// We need to prepend a set of profile handle arguments...
@ -407,7 +439,10 @@ func {{FNAME}}({{GO_ARGS_SPEC}}) {
if cwtchProfile != nil {
functionality := {{EXPERIMENT}}.FunctionalityGate()
if functionality != nil {
functionality.{{LIBNAME}}(cwtchProfile, {{GO_ARG}})
err := functionality.{{LIBNAME}}(cwtchProfile, {{GO_ARG}})
if err != nil {
log.Errorf("error calling experimental feature {{FNAME}}: %v", err)
}
}
}
}

7
go.mod
View File

@ -1,11 +1,11 @@
module git.openprivacy.ca/cwtch.im/cwtch-autobindings
go 1.19
go 1.20
require (
cwtch.im/cwtch v0.21.0
cwtch.im/cwtch v0.27.0
git.openprivacy.ca/cwtch.im/server v1.4.5
git.openprivacy.ca/openprivacy/connectivity v1.10.0
git.openprivacy.ca/openprivacy/connectivity v1.11.0
git.openprivacy.ca/openprivacy/log v1.0.3
github.com/mutecomm/go-sqlcipher/v4 v4.4.2
)
@ -24,5 +24,4 @@ require (
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 // indirect
golang.org/x/tools v0.1.12 // indirect
)

8
go.sum
View File

@ -1,6 +1,6 @@
cwtch.im/cwtch v0.18.0/go.mod h1:StheazFFY7PKqBbEyDVLhzWW6WOat41zV0ckC240c5Y=
cwtch.im/cwtch v0.21.0 h1:mZotCp9OOnP+FOX0OnrmdXDqZs0cufT2shLgUyZEW7c=
cwtch.im/cwtch v0.21.0/go.mod h1:h8S7EgEM+8pE1k+XLB5jAFdIPlOzwoXEY0GH5mQye5A=
cwtch.im/cwtch v0.27.0 h1:MkNIZ+pT5ZwiGlKHk20GMUTlzBsmCWJEibbj6hr+WHw=
cwtch.im/cwtch v0.27.0/go.mod h1:A3i92aFuhyHI2DYO2Qnvl5iqEw0Cox22pdiypHnMOy4=
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
@ -13,8 +13,8 @@ git.openprivacy.ca/openprivacy/bine v0.0.4/go.mod h1:13ZqhKyqakDsN/ZkQkIGNULsmLy
git.openprivacy.ca/openprivacy/bine v0.0.5 h1:DJs5gqw3SkvLSgRDvroqJxZ7F+YsbxbBRg5t0rU5gYE=
git.openprivacy.ca/openprivacy/bine v0.0.5/go.mod h1:fwdeq6RO08WDkV0k7HfArsjRvurVULoUQmT//iaABZM=
git.openprivacy.ca/openprivacy/connectivity v1.8.6/go.mod h1:Hn1gpOx/bRZp5wvCtPQVJPXrfeUH0EGiG/Aoa0vjGLg=
git.openprivacy.ca/openprivacy/connectivity v1.10.0 h1:7P5xdFL4mGg9bwlIY+sdaNGUMazlMB82/v/6kXlvqxY=
git.openprivacy.ca/openprivacy/connectivity v1.10.0/go.mod h1:OQO1+7OIz/jLxDrorEMzvZA6SEbpbDyLGpjoFqT3z1Y=
git.openprivacy.ca/openprivacy/connectivity v1.11.0 h1:roASjaFtQLu+HdH5fa2wx6F00NL3YsUTlmXBJh8aLZk=
git.openprivacy.ca/openprivacy/connectivity v1.11.0/go.mod h1:OQO1+7OIz/jLxDrorEMzvZA6SEbpbDyLGpjoFqT3z1Y=
git.openprivacy.ca/openprivacy/log v1.0.3 h1:E/PMm4LY+Q9s3aDpfySfEDq/vYQontlvNj/scrPaga0=
git.openprivacy.ca/openprivacy/log v1.0.3/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=

View File

@ -3,22 +3,29 @@
echo "Checking code quality (you want to see no output here)"
echo ""
echo "Vetting:"
go vet generate/*
echo ""
echo "Linting:"
echo "Running staticcheck..."
staticcheck ./generate
staticcheck lib.go
staticcheck ./utils/*
# In the future we should remove include-pkgs. However, there are a few false positives in the overall go stdlib that make this
# too noisy right now, specifically assigning nil to initialize slices (safe), and using go internal context channels assigned
# nil (also safe).
# We also have one file infinite_channel.go written in a way that static analysis cannot reason about easily. So it is explictly
# ignored.
echo "Running nilaway..."
nilaway -include-pkgs="git.openprivacy.ca/cwtch.im/cwtch-autobindings,cwtch.im/cwtch,cwtch.im/tapir,git.openprivacy.ca/openprivacy/connectivity" -exclude-errors-in-files="./templates/lib_template.go" -exclude-file-docstrings="nolint:nilaway" lib.go
nilaway -include-pkgs="git.openprivacy.ca/cwtch.im/cwtch-autobindings,cwtch.im/cwtch,cwtch.im/tapir,git.openprivacy.ca/openprivacy/connectivity" -exclude-errors-in-files="./templates/lib_template.go" -exclude-file-docstrings="nolint:nilaway" ./utils/
echo "Time to format"
gofmt -l -s -w .
gofmt -l -s -w ./utils/*
gofmt -l -s -w ./generate/*
# ineffassign (https://github.com/gordonklaus/ineffassign)
echo "Checking for ineffectual assignment of errors (unchecked errors...)"
ineffassign .
# echo "Checking for ineffectual assignment of errors (unchecked errors...)"
# ineffassign .
# misspell (https://github.com/client9/misspell/cmd/misspell)
echo "Checking for misspelled words..."
misspell . | grep -v "testing/" | grep -v "vendor/" | grep -v "go.sum" | grep -v ".idea"
# echo "Checking for misspelled words..."
# misspell . | grep -v "testing/" | grep -v "vendor/" | grep -v "go.sum" | grep -v ".idea"

21
spec
View File

@ -3,6 +3,7 @@
# Peer Engine
app ActivatePeerEngine profile
app DeactivatePeerEngine profile
app ConfigureConnections profile bool:listen bool:peers bool:servers
# Profile Management
app CreateProfile name password bool:autostart
@ -20,17 +21,31 @@ profile BlockConversation conversation
profile UnblockConversation conversation
profile DeleteConversation conversation
profile PeerWithOnion string:handle
profile DisconnectFromPeer string:handle
(json-err)profile EnhancedGetConversationAccessControlList conversation
profile EnhancedUpdateConversationAccessControlList conversation string:json
# Search
(json)profile SearchConversations string:pattern
# Message Management
(json)profile EnhancedSendMessage conversation string:msg
(json)profile EnhancedGetMessageById conversation message
(json)profile EnhancedGetMessageByContentHash conversation string:contentHash
(json)profile EnhancedGetMessages conversation int:index int:count
(json)profile EnhancedGetMessages conversation int:index uint:count
(json)profile EnhancedSendInviteMessage conversation conversation:target
profile UpdateMessageAttribute conversation channel message string:attributeKey string:attributeValue
# Group Management
profile StartGroup string:name string:server
profile QueueJoinServer string:handle
profile DisconnectFromServer string:handle
## Server List Management...
import "cwtch.im/cwtch/functionality/servers"
@profile-experiment PublishServerUpdate servers
@profile-experiment GetServerInfoList servers
@profile-experiment DeleteServerInfo servers string:serverOnion
# Filesharing Management
import "cwtch.im/cwtch/functionality/filesharing"
@ -44,8 +59,8 @@ import "cwtch.im/cwtch/functionality/filesharing"
# Server Hosting Experiment
!serverExperiment import "git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/servers"
!serverExperiment global serverExperiment *servers.ServersFunctionality servers
!serverExperiment import "git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/server_hosting"
!serverExperiment global serverExperiment *server_hosting.ServersFunctionality server_hosting
!serverExperiment exp CreateServer application password string:description bool:autostart
!serverExperiment exp SetServerAttribute application string:handle string:key string:val
!serverExperiment exp LoadServers application acn password

View File

@ -22,6 +22,7 @@ import (
"runtime"
"runtime/pprof"
"strings"
"strconv"
"time"
mrand "math/rand"
"crypto/rand"
@ -189,7 +190,6 @@ func _startCwtch(appDir string, torPath string) {
log.Infof("libcwtch-go application launched")
application.GetPrimaryBus().Publish(event.NewEvent(settings.CwtchStarted, map[event.Field]string{}))
application.QueryACNVersion()
application.LoadProfiles(app.DefactoPasswordForUnencryptedProfiles)
{{EXPERIMENT_REGISTER}}
@ -247,7 +247,7 @@ func ReconnectCwtchForeground() {
settingsJson, _ := json.Marshal(application.ReadSettings())
application.GetPrimaryBus().Publish(event.NewEvent(settings.UpdateGlobalSettings, map[event.Field]string{event.Data: string(settingsJson)}))
application.GetPrimaryBus().Publish(event.NewEvent(settings.CwtchStarted, map[event.Field]string{}))
application.GetPrimaryBus().Publish(event.NewEvent(settings.CwtchStarted, map[event.Field]string{utils.ReloadEvent: event.True}))
application.QueryACNStatus()
application.QueryACNVersion()
}
@ -314,6 +314,8 @@ func SetProfileAttribute(profileOnion string, key string, value string) {
profile.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.ProfileStatus, value)
} else if zone == attr.ProfileZone && key == constants.PeerAutostart {
profile.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAutostart, value)
} else if zone == attr.ProfileZone && key == constants.PeerAppearOffline {
profile.SetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAppearOffline, value)
} else {
log.Errorf("attempted to set an attribute with an unknown zone: %v", key)
}
@ -440,7 +442,6 @@ const (
func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir string) (connectivity.ACN, settings.GlobalSettings, error) {
mrand.Seed(int64(time.Now().Nanosecond()))
socksPort := mrand.Intn(1000) + 9600
controlPort := socksPort + 1
@ -469,7 +470,30 @@ func buildACN(globalSettings settings.GlobalSettings, torPath string, appDir str
// Override Ports if on Tails...
if cwtchTails := os.Getenv("CWTCH_TAILS"); strings.ToLower(cwtchTails) == "true" {
log.Infof("CWTCH_TAILS environment variable set... overriding tor config...")
controlPort = 9051
// In tails 5.13 the control port was changed to 951
// so read the Tails Version File and if it exists...
b, err := os.ReadFile("/etc/amnesia/version")
if err == nil {
// the file should start with the version followed
// by a space...
versionEnd := strings.Index(string(b), " ")
versionStr := string(b)[:versionEnd]
version, err := strconv.ParseFloat(versionStr, 64)
if err == nil {
log.Infof("Confirming Tails Version: %v", version)
// assert the control port if we are at the dedicated version...
// we know this change happened sometime after 5.11
if version >= 5.13 {
controlPort = 951
}
} else {
log.Errorf("Unable to confirm Tails version. CWTCH_TAILS options may not function correctly.")
}
}
socksPort = 9050
globalSettings.CustomControlPort = controlPort
globalSettings.CustomSocksPort = socksPort

View File

@ -1,23 +1,22 @@
package utils
import (
"cwtch.im/cwtch/settings"
"encoding/json"
"fmt"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/servers"
"os"
"strconv"
"cwtch.im/cwtch/app"
"cwtch.im/cwtch/app/plugins"
"cwtch.im/cwtch/functionality/servers"
"cwtch.im/cwtch/model"
"cwtch.im/cwtch/model/attr"
"cwtch.im/cwtch/model/constants"
"cwtch.im/cwtch/peer"
"cwtch.im/cwtch/protocol/connections"
"cwtch.im/cwtch/settings"
"encoding/json"
"fmt"
constants2 "git.openprivacy.ca/cwtch.im/cwtch-autobindings/constants"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/features/groups"
"git.openprivacy.ca/cwtch.im/cwtch-autobindings/experiments/server_hosting"
"git.openprivacy.ca/openprivacy/log"
"os"
"strconv"
"time"
@ -66,10 +65,10 @@ func (eh *EventHandler) HandleApp(application app.Application) {
application.GetPrimaryBus().Subscribe(event.ACNVersion, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(settings.UpdateGlobalSettings, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(settings.CwtchStarted, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(servers.NewServer, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(servers.ServerIntentUpdate, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(servers.ServerDeleted, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(servers.ServerStatsUpdate, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(server_hosting.NewServer, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(server_hosting.ServerIntentUpdate, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(server_hosting.ServerDeleted, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(server_hosting.ServerStatsUpdate, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(event.StartingStorageMiragtion, eh.appBusQueue)
application.GetPrimaryBus().Subscribe(event.DoneStorageMigration, eh.appBusQueue)
}
@ -146,9 +145,15 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
// Start up the Profile
if acnStatus == 100 {
autostart, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants2.PeerAutostart)
autostart, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAutostart)
appearOffline, appearOfflineExists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAppearOffline)
if !exists || autostart == "true" {
eh.app.ActivatePeerEngine(onion)
if appearOfflineExists && appearOffline == "true" {
// don't configure any connections...
} else {
eh.app.ConfigureConnections(onion, true, true, true)
}
}
}
@ -162,6 +167,13 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
}
e.Data["autostart"] = autostart
appearOffline, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.ProfileZone, constants.PeerAppearOffline)
// legacy profiles should not appearOffline by default
if !exists {
appearOffline = "false"
}
e.Data["appearOffline"] = appearOffline
// Name always exists
e.Data[constants.Name], _ = profile.GetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.Name)
e.Data[constants2.DefaultProfilePicture] = RandomProfileImage(onion)
@ -174,7 +186,7 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
}
// Construct our conversations and our srever lists
var contacts []Contact
var servers []groups.Server
var knownServers []servers.Server
conversations, err := profile.FetchConversations()
@ -186,9 +198,10 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
// has been disabled and then is later re-enabled. As such we need to ensure that this list is
// re-fetched when the group experiment is enabled via a dedicated ListServerInfo event...
if conversationInfo.IsServer() {
groupHandler, err := groups.ExperimentGate(eh.app.ReadSettings().Experiments)
groupHandler := servers.FunctionalityGate()
if err == nil {
servers = append(servers, groupHandler.GetServerInfo(conversationInfo.Handle, profile))
serverInfo, _ := groupHandler.GetServerInfo(profile, conversationInfo.Handle)
knownServers = append(knownServers, serverInfo)
}
continue
}
@ -211,7 +224,7 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
cpicPath = RandomGroupImage(conversationInfo.Handle)
defaultPath = RandomGroupImage(conversationInfo.Handle)
} else {
cpicPath = GetProfileImage(profile, conversationInfo, settings.DownloadPath)
cpicPath = eh.GetProfileImage(profile, conversationInfo, settings.DownloadPath)
defaultPath = RandomProfileImage(conversationInfo.Handle)
}
@ -309,8 +322,8 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
e.Data["ContactsJson"] = string(bytes)
// Marshal the server list into the new peer event...
serversListBytes, _ := json.Marshal(servers)
e.Data[groups.ServerList] = string(serversListBytes)
serversListBytes, _ := json.Marshal(knownServers)
e.Data[servers.ServerList] = string(serversListBytes)
log.Debugf("contactsJson %v", e.Data["ContactsJson"])
}
@ -320,15 +333,17 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
return string(json)
}
func GetProfileImage(profile peer.CwtchPeer, conversationInfo *model.Conversation, basepath string) string {
fileKey, err := profile.GetConversationAttribute(conversationInfo.ID, attr.PublicScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants.CustomProfileImageKey)))
if err == nil {
if value, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey)); exists && value == event.True {
fp, _ := filesharing.GenerateDownloadPath(basepath, fileKey, true)
// check if the file exists...if it does then set the path...
if _, err := os.Stat(fp); err == nil {
image, _ := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.path", fileKey))
return image
func (eh *EventHandler) GetProfileImage(profile peer.CwtchPeer, conversationInfo *model.Conversation, basepath string) string {
if eh.app.IsFeatureEnabled(constants.ImagePreviewsExperiment) {
fileKey, err := profile.GetConversationAttribute(conversationInfo.ID, attr.PublicScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants.CustomProfileImageKey)))
if err == nil {
if value, exists := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.complete", fileKey)); exists && value == event.True {
fp, _ := filesharing.GenerateDownloadPath(basepath, fileKey, true)
// check if the file exists...if it does then set the path...
if _, err := os.Stat(fp); err == nil {
image, _ := profile.GetScopedZonedAttribute(attr.LocalScope, attr.FilesharingZone, fmt.Sprintf("%s.path", fileKey))
return image
}
}
}
}
@ -344,6 +359,10 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
log.Errorf("eh.app == nil in handleProfileEvent... this shouldnt happen?")
} else {
profile := eh.app.GetPeer(ev.Profile)
if profile == nil {
log.Errorf("something has gone very wrong. profile is nil in handleProfileEvent")
return ""
}
log.Debugf("New Profile Event to Handle: %v", ev)
switch ev.Event.EventType {
case event.NewMessageFromPeer: //event.TimestampReceived, event.RemotePeer, event.Data
@ -353,7 +372,7 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
if ci != nil && err == nil {
ev.Event.Data[event.ConversationID] = strconv.Itoa(ci.ID)
profile.SetConversationAttribute(ci.ID, attr.LocalScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants2.Archived)), event.False)
ev.Event.Data[constants2.Picture] = GetProfileImage(profile, ci, eh.app.ReadSettings().DownloadPath)
ev.Event.Data[constants2.Picture] = eh.GetProfileImage(profile, ci, eh.app.ReadSettings().DownloadPath)
} else {
// TODO This Conversation May Not Exist Yet...But we are not in charge of creating it...
log.Errorf("todo wait for contact to be added before processing this event...")
@ -382,13 +401,17 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
ev.Event.Data["Nick"] = ev.Event.Data["RemotePeer"]
}
}
ev.Event.Data[constants2.Picture] = GetProfileImage(profile, ci, eh.app.ReadSettings().DownloadPath)
ev.Event.Data[constants2.Picture] = eh.GetProfileImage(profile, ci, eh.app.ReadSettings().DownloadPath)
}
conversationID, _ := strconv.Atoi(ev.Event.Data[event.ConversationID])
profile.SetConversationAttribute(conversationID, attr.LocalScope.ConstructScopedZonedPath(attr.ProfileZone.ConstructZonedPath(constants2.Archived)), event.False)
gci, _ := profile.GetConversationInfo(conversationID)
gci, err := profile.GetConversationInfo(conversationID)
if err != nil {
log.Errorf("new message from non-existant group: %v", err)
break
}
groupServer := gci.Attributes[attr.LocalScope.ConstructScopedZonedPath(attr.LegacyGroupZone.ConstructZonedPath(constants.GroupServer)).ToString()]
state := profile.GetPeerState(groupServer)
// if syncing, don't flood with notifications
@ -407,11 +430,13 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
count, err := profile.GetChannelMessageCount(conversationID, 0)
if err != nil {
log.Errorf("error fetching channel message count %v %v", conversationID, err)
break
}
conversationInfo, err := profile.GetConversationInfo(conversationID)
if err != nil {
log.Errorf("error fetching conversation info for %v %v", conversationID, err)
break
}
blocked := constants.False
@ -424,7 +449,11 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
accepted = constants.True
}
acl, _ := json.Marshal(conversationInfo.ACL)
acl, err := json.Marshal(conversationInfo.ACL)
if err != nil {
log.Errorf("received invalid ACL in conversation: %v", err)
break
}
lastMessage, _ := profile.GetMostRecentMessages(conversationID, 0, 0, 1)
ev.Event.Data["unread"] = strconv.Itoa(count) // if this is a new contact with messages attached then by-definition these are unread...
@ -444,8 +473,16 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
groupPic := RandomGroupImage(ev.Event.Data[event.GroupID])
ev.Event.Data[constants2.Picture] = groupPic
conversationID, _ := strconv.Atoi(ev.Event.Data[event.ConversationID])
conversationInfo, _ := profile.GetConversationInfo(conversationID)
conversationID, err := strconv.Atoi(ev.Event.Data[event.ConversationID])
if err != nil {
log.Errorf("invalid conversation id recieved %v", err)
break
}
conversationInfo, err := profile.GetConversationInfo(conversationID)
if err != nil {
log.Errorf("error fetching conversation info for %v %v", conversationID, err)
break
}
acl, _ := json.Marshal(conversationInfo.ACL)
ev.Event.Data["accessControlList"] = string(acl)
case event.NewGroup:
@ -456,51 +493,34 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
groupPic := RandomGroupImage(invite.GroupID)
ev.Event.Data[constants2.Picture] = groupPic
conversationID, _ := strconv.Atoi(ev.Event.Data[event.ConversationID])
conversationInfo, _ := profile.GetConversationInfo(conversationID)
acl, _ := json.Marshal(conversationInfo.ACL)
conversationID, err := strconv.Atoi(ev.Event.Data[event.ConversationID])
if err != nil {
log.Errorf("invalid conversation id recieved %v", err)
break
}
conversationInfo, err := profile.GetConversationInfo(conversationID)
if err != nil {
log.Errorf("error fetching conversation info for %v %v", conversationID, err)
break
}
acl, err := json.Marshal(conversationInfo.ACL)
ev.Event.Data["accessControlList"] = string(acl)
if err != nil {
log.Errorf("received invalid ACL in conversation: %v", err)
break
}
} else {
log.Errorf("received a new group event which contained an invalid invite %v. this should never happen and likely means there is a bug in cwtch. Please file a ticket @ https://git.openprivacy.ca/cwtch.im/cwtch", err)
return ""
}
case event.PeerStateChange:
cxnState := connections.ConnectionStateToType()[ev.Event.Data[event.ConnectionState]]
// skip events the UI doesn't act on
if cxnState == connections.CONNECTING || cxnState == connections.CONNECTED {
return ""
}
contact, err := profile.FetchConversationInfo(ev.Event.Data[event.RemotePeer])
if ev.Event.Data[event.RemotePeer] == profile.GetOnion() {
return "" // suppress events from our own profile...
}
// We do not know who this is...don't send any event until we see a message from them
// (at that point the conversation will have been created...)
if contact == nil || err != nil || contact.ID == 0 {
return ""
}
// if we already know this state, suppress
if knownState, exists := contactStateCache[ev.Event.Data[event.RemotePeer]]; exists && cxnState == knownState {
return ""
}
contactStateCache[ev.Event.Data[event.RemotePeer]] = cxnState
case event.ServerStateChange:
cxnState := connections.ConnectionStateToType()[ev.Event.Data[event.ConnectionState]]
// skip events the UI doesn't act on
if cxnState == connections.CONNECTING || cxnState == connections.CONNECTED {
return ""
}
// if we already know this state, suppress
if knownState, exists := contactStateCache[ev.Event.Data[event.RemotePeer]]; exists && cxnState == knownState {
return ""
}
contactStateCache[ev.Event.Data[event.RemotePeer]] = cxnState
case event.TokenManagerInfo:
conversations, err := profile.FetchConversations()
@ -546,6 +566,10 @@ func unwrap(original *EventProfileEnvelope) *event.Event {
func (eh *EventHandler) startHandlingPeer(onion string) {
eventBus := eh.app.GetEventBus(onion)
if eventBus == nil {
log.Errorf("could not start handling peer events .. event bus is nil")
return
}
q := event.NewQueue()
eventBus.Subscribe(event.NetworkStatus, q)
@ -572,6 +596,9 @@ func (eh *EventHandler) startHandlingPeer(onion string) {
eventBus.Subscribe(event.FileDownloaded, q)
eventBus.Subscribe(event.TokenManagerInfo, q)
eventBus.Subscribe(event.ProtocolEngineCreated, q)
eventBus.Subscribe(event.SearchResult, q)
eventBus.Subscribe(event.SearchCancelled, q)
eventBus.Subscribe(servers.UpdateServerInfo, q)
go eh.forwardProfileMessages(onion, q)
}