forked from cwtch.im/cwtch
Merge pull request 'Allow Explicit Server Resyncing' (#361) from peer_fixes into master
Reviewed-on: cwtch.im/cwtch#361
This commit is contained in:
commit
f958719ecf
|
@ -91,7 +91,7 @@ func (ac *applicationCore) CreatePeer(name string) (*model.Profile, error) {
|
||||||
|
|
||||||
_, exists := ac.eventBuses[profile.Onion]
|
_, exists := ac.eventBuses[profile.Onion]
|
||||||
if exists {
|
if exists {
|
||||||
return nil, fmt.Errorf("Error: profile for onion %v already exists", profile.Onion)
|
return nil, fmt.Errorf("error: profile for onion %v already exists", profile.Onion)
|
||||||
}
|
}
|
||||||
|
|
||||||
eventBus := event.NewEventManager()
|
eventBus := event.NewEventManager()
|
||||||
|
@ -178,7 +178,7 @@ func (app *application) AddPeerPlugin(onion string, pluginID plugins.PluginID) {
|
||||||
func (ac *applicationCore) LoadProfiles(password string, timeline bool, loadProfileFn LoadProfileFn) error {
|
func (ac *applicationCore) LoadProfiles(password string, timeline bool, loadProfileFn LoadProfileFn) error {
|
||||||
files, err := ioutil.ReadDir(path.Join(ac.directory, "profiles"))
|
files, err := ioutil.ReadDir(path.Join(ac.directory, "profiles"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error: cannot read profiles directory: %v", err)
|
return fmt.Errorf("error: cannot read profiles directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
|
|
|
@ -79,7 +79,7 @@ func (cr *contactRetry) run() {
|
||||||
|
|
||||||
case event.ACNStatus:
|
case event.ACNStatus:
|
||||||
prog := e.Data[event.Progress]
|
prog := e.Data[event.Progress]
|
||||||
if prog == "100" && cr.networkUp == false {
|
if prog == "100" && !cr.networkUp {
|
||||||
cr.networkUp = true
|
cr.networkUp = true
|
||||||
cr.connections.Range(func(k, v interface{}) bool {
|
cr.connections.Range(func(k, v interface{}) bool {
|
||||||
p := v.(*contact)
|
p := v.(*contact)
|
||||||
|
|
|
@ -64,7 +64,7 @@ func (nc *networkCheck) run() {
|
||||||
if _, exists := nc.onionsToCheck.Load(e.Data[event.Onion]); !exists {
|
if _, exists := nc.onionsToCheck.Load(e.Data[event.Onion]); !exists {
|
||||||
log.Debugf("initiating connection check for %v", e.Data[event.Onion])
|
log.Debugf("initiating connection check for %v", e.Data[event.Onion])
|
||||||
nc.onionsToCheck.Store(e.Data[event.Onion], true)
|
nc.onionsToCheck.Store(e.Data[event.Onion], true)
|
||||||
if time.Now().Sub(lastMessageReceived) > time.Minute {
|
if time.Since(lastMessageReceived) > time.Minute {
|
||||||
nc.selfTest()
|
nc.selfTest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func (nc *networkCheck) run() {
|
||||||
}
|
}
|
||||||
case <-time.After(tickTime):
|
case <-time.After(tickTime):
|
||||||
// if we haven't received an action in the last minute...kick off a set of testing
|
// if we haven't received an action in the last minute...kick off a set of testing
|
||||||
if time.Now().Sub(lastMessageReceived) > time.Minute {
|
if time.Since(lastMessageReceived) > time.Minute {
|
||||||
nc.selfTest()
|
nc.selfTest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,9 +165,9 @@ func (tp *TimeoutPolicy) ExecuteAction(action func() error) error {
|
||||||
c <- action()
|
c <- action()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
tick := time.Tick(time.Duration(*tp))
|
tick := time.NewTicker(time.Duration(*tp))
|
||||||
select {
|
select {
|
||||||
case <-tick:
|
case <-tick.C:
|
||||||
return fmt.Errorf("ActionTimedOutError")
|
return fmt.Errorf("ActionTimedOutError")
|
||||||
case err := <-c:
|
case err := <-c:
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
// however for small utility use, this function which polls the app until the peer is created
|
// however for small utility use, this function which polls the app until the peer is created
|
||||||
// may fill that usecase better
|
// may fill that usecase better
|
||||||
func WaitGetPeer(app app2.Application, name string) peer.CwtchPeer {
|
func WaitGetPeer(app app2.Application, name string) peer.CwtchPeer {
|
||||||
for true {
|
for {
|
||||||
for id := range app.ListPeers() {
|
for id := range app.ListPeers() {
|
||||||
peer := app.GetPeer(id)
|
peer := app.GetPeer(id)
|
||||||
localName, _ := peer.GetAttribute(attr.GetLocalScope("name"))
|
localName, _ := peer.GetAttribute(attr.GetLocalScope("name"))
|
||||||
|
@ -22,5 +22,4 @@ func WaitGetPeer(app app2.Application, name string) peer.CwtchPeer {
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,10 +169,7 @@ func (pb *pipeBridge) threeShakeClient() bool {
|
||||||
if string(resp) == synack {
|
if string(resp) == synack {
|
||||||
stop <- true
|
stop <- true
|
||||||
err := pb.writeString([]byte(ack))
|
err := pb.writeString([]byte(ack))
|
||||||
if err != nil {
|
return err == nil
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,6 +230,10 @@ const (
|
||||||
// Onion: the local onion we attempt to check
|
// Onion: the local onion we attempt to check
|
||||||
NetworkStatus = Type("NetworkError")
|
NetworkStatus = Type("NetworkError")
|
||||||
|
|
||||||
|
// Notify the UI that a Server has been added
|
||||||
|
// Onion = Server Onion
|
||||||
|
ServerCreated = Type("ServerAdded")
|
||||||
|
|
||||||
// For debugging. Allows test to emit a Syn and get a response Ack(eventID) when the subsystem is done processing a queue
|
// For debugging. Allows test to emit a Syn and get a response Ack(eventID) when the subsystem is done processing a queue
|
||||||
Syn = Type("Syn")
|
Syn = Type("Syn")
|
||||||
Ack = Type("Ack")
|
Ack = Type("Ack")
|
||||||
|
|
|
@ -99,7 +99,7 @@ func (em *manager) Subscribe(eventType Type, queue Queue) {
|
||||||
|
|
||||||
// Publish takes an Event and sends it to the internal eventBus where it is distributed to all Subscribers
|
// Publish takes an Event and sends it to the internal eventBus where it is distributed to all Subscribers
|
||||||
func (em *manager) Publish(event Event) {
|
func (em *manager) Publish(event Event) {
|
||||||
if event.EventType != "" && em.closed != true {
|
if event.EventType != "" && !em.closed {
|
||||||
|
|
||||||
// Debug Events for Tracing, locked behind an environment variable
|
// Debug Events for Tracing, locked behind an environment variable
|
||||||
// for now.
|
// for now.
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -3,13 +3,15 @@ module cwtch.im/cwtch
|
||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.openprivacy.ca/cwtch.im/tapir v0.4.1
|
git.openprivacy.ca/cwtch.im/tapir v0.4.2
|
||||||
git.openprivacy.ca/openprivacy/connectivity v1.4.3
|
git.openprivacy.ca/openprivacy/connectivity v1.4.3
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.2
|
git.openprivacy.ca/openprivacy/log v1.0.2
|
||||||
github.com/gtank/ristretto255 v0.1.2
|
github.com/gtank/ristretto255 v0.1.2
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
github.com/struCoder/pidusage v0.1.3
|
github.com/struCoder/pidusage v0.1.3
|
||||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee
|
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee
|
||||||
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
|
||||||
|
golang.org/x/tools v0.1.2 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
)
|
)
|
||||||
|
|
19
go.sum
19
go.sum
|
@ -12,6 +12,8 @@ git.openprivacy.ca/cwtch.im/tapir v0.4.0 h1:clG8uORt0NKEhT4P+Dpw1pzyUuYzYBMevGqn
|
||||||
git.openprivacy.ca/cwtch.im/tapir v0.4.0/go.mod h1:eH6dZxXrhW0C4KZX18ksUa6XJCrEvtg8cJJ/Fy6gv+E=
|
git.openprivacy.ca/cwtch.im/tapir v0.4.0/go.mod h1:eH6dZxXrhW0C4KZX18ksUa6XJCrEvtg8cJJ/Fy6gv+E=
|
||||||
git.openprivacy.ca/cwtch.im/tapir v0.4.1 h1:9LMpQX41IzecNNlRc1FZKXHg6wlFss679tFsa3vzb3Y=
|
git.openprivacy.ca/cwtch.im/tapir v0.4.1 h1:9LMpQX41IzecNNlRc1FZKXHg6wlFss679tFsa3vzb3Y=
|
||||||
git.openprivacy.ca/cwtch.im/tapir v0.4.1/go.mod h1:eH6dZxXrhW0C4KZX18ksUa6XJCrEvtg8cJJ/Fy6gv+E=
|
git.openprivacy.ca/cwtch.im/tapir v0.4.1/go.mod h1:eH6dZxXrhW0C4KZX18ksUa6XJCrEvtg8cJJ/Fy6gv+E=
|
||||||
|
git.openprivacy.ca/cwtch.im/tapir v0.4.2 h1:bxMWZnVJXX4dqqOFS7ELW4iFkVL4GS8wiRkjRv5rJe8=
|
||||||
|
git.openprivacy.ca/cwtch.im/tapir v0.4.2/go.mod h1:eH6dZxXrhW0C4KZX18ksUa6XJCrEvtg8cJJ/Fy6gv+E=
|
||||||
git.openprivacy.ca/openprivacy/bine v0.0.4 h1:CO7EkGyz+jegZ4ap8g5NWRuDHA/56KKvGySR6OBPW+c=
|
git.openprivacy.ca/openprivacy/bine v0.0.4 h1:CO7EkGyz+jegZ4ap8g5NWRuDHA/56KKvGySR6OBPW+c=
|
||||||
git.openprivacy.ca/openprivacy/bine v0.0.4/go.mod h1:13ZqhKyqakDsN/ZkQkIGNULsmLyqtXc46XBcnuXm/mU=
|
git.openprivacy.ca/openprivacy/bine v0.0.4/go.mod h1:13ZqhKyqakDsN/ZkQkIGNULsmLyqtXc46XBcnuXm/mU=
|
||||||
git.openprivacy.ca/openprivacy/connectivity v1.4.0 h1:c7AANUCrlA4hIqXxIGDOWMtSe8CpDleD1877PShScbM=
|
git.openprivacy.ca/openprivacy/connectivity v1.4.0 h1:c7AANUCrlA4hIqXxIGDOWMtSe8CpDleD1877PShScbM=
|
||||||
|
@ -50,16 +52,25 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/struCoder/pidusage v0.1.3 h1:pZcSa6asBE38TJtW0Nui6GeCjLTpaT/jAnNP7dUTLSQ=
|
github.com/struCoder/pidusage v0.1.3 h1:pZcSa6asBE38TJtW0Nui6GeCjLTpaT/jAnNP7dUTLSQ=
|
||||||
github.com/struCoder/pidusage v0.1.3/go.mod h1:pWBlW3YuSwRl6h7R5KbvA4N8oOqe9LjaKW5CwT1SPjI=
|
github.com/struCoder/pidusage v0.1.3/go.mod h1:pWBlW3YuSwRl6h7R5KbvA4N8oOqe9LjaKW5CwT1SPjI=
|
||||||
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
||||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
|
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
|
||||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||||
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -67,6 +78,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
@ -74,6 +86,13 @@ golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
|
||||||
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
|
|
|
@ -52,8 +52,8 @@ func NewGroup(server string) (*Group, error) {
|
||||||
group.Version = CurrentGroupVersion
|
group.Version = CurrentGroupVersion
|
||||||
group.LocalID = GenerateRandomID()
|
group.LocalID = GenerateRandomID()
|
||||||
group.Accepted = true // we are starting a group, so we assume we want to connect to it...
|
group.Accepted = true // we are starting a group, so we assume we want to connect to it...
|
||||||
if tor.IsValidHostname(server) == false {
|
if !tor.IsValidHostname(server) {
|
||||||
return nil, errors.New("Server is not a valid v3 onion")
|
return nil, errors.New("server is not a valid v3 onion")
|
||||||
}
|
}
|
||||||
|
|
||||||
group.GroupServer = server
|
group.GroupServer = server
|
||||||
|
@ -251,7 +251,7 @@ func ValidateInvite(invite string) (*groups.GroupInvite, error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
||||||
// Validate the Invite by first checking that the server is a valid v3 onion
|
// Validate the Invite by first checking that the server is a valid v3 onion
|
||||||
if tor.IsValidHostname(gci.ServerHost) == false {
|
if !tor.IsValidHostname(gci.ServerHost) {
|
||||||
return nil, errors.New("server is not a valid v3 onion")
|
return nil, errors.New("server is not a valid v3 onion")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ func DeserializeAndVerify(bundle []byte) (*KeyBundle, error) {
|
||||||
var decodedPub []byte
|
var decodedPub []byte
|
||||||
decodedPub, err = base32.StdEncoding.DecodeString(strings.ToUpper(string(serverKey)))
|
decodedPub, err = base32.StdEncoding.DecodeString(strings.ToUpper(string(serverKey)))
|
||||||
if err == nil && len(decodedPub) == 35 {
|
if err == nil && len(decodedPub) == 35 {
|
||||||
if ed25519.Verify(decodedPub[:32], keyBundle.Serialize(), signature) == true {
|
if ed25519.Verify(decodedPub[:32], keyBundle.Serialize(), signature) { // == true
|
||||||
return keyBundle, nil
|
return keyBundle, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,7 @@ type ModifyGroups interface {
|
||||||
// ModifyServers provides write-only access to servers
|
// ModifyServers provides write-only access to servers
|
||||||
type ModifyServers interface {
|
type ModifyServers interface {
|
||||||
AddServer(string) error
|
AddServer(string) error
|
||||||
|
ResyncServer(onion string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendMessages enables a caller to sender messages to a contact
|
// SendMessages enables a caller to sender messages to a contact
|
||||||
|
@ -306,7 +307,7 @@ func (cp *cwtchPeer) AddServer(serverSpecification string) error {
|
||||||
// TODO if the key bundle is incomplete then error out. In the future we may allow servers to attest to new
|
// TODO if the key bundle is incomplete then error out. In the future we may allow servers to attest to new
|
||||||
// keys or subsets of keys, but for now they must commit only to a complete set of keys required for Cwtch Groups
|
// keys or subsets of keys, but for now they must commit only to a complete set of keys required for Cwtch Groups
|
||||||
// (that way we can be assured that the keybundle we store is a valid one)
|
// (that way we can be assured that the keybundle we store is a valid one)
|
||||||
if keyBundle.HasKeyType(model.KeyTypeTokenOnion) == false || keyBundle.HasKeyType(model.KeyTypeServerOnion) == false || keyBundle.HasKeyType(model.KeyTypePrivacyPass) == false {
|
if !keyBundle.HasKeyType(model.KeyTypeTokenOnion) || !keyBundle.HasKeyType(model.KeyTypeServerOnion) || !keyBundle.HasKeyType(model.KeyTypePrivacyPass) {
|
||||||
return errors.New("keybundle is incomplete")
|
return errors.New("keybundle is incomplete")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +327,8 @@ func (cp *cwtchPeer) AddServer(serverSpecification string) error {
|
||||||
cp.mutex.Unlock()
|
cp.mutex.Unlock()
|
||||||
|
|
||||||
pd, _ := json.Marshal(pp)
|
pd, _ := json.Marshal(pp)
|
||||||
|
|
||||||
|
// Sync the Storage Engine
|
||||||
cp.eventBus.Publish(event.NewEvent(event.PeerCreated, map[event.Field]string{
|
cp.eventBus.Publish(event.NewEvent(event.PeerCreated, map[event.Field]string{
|
||||||
event.Data: string(pd),
|
event.Data: string(pd),
|
||||||
event.RemotePeer: onion,
|
event.RemotePeer: onion,
|
||||||
|
@ -473,6 +476,20 @@ func (cp *cwtchPeer) JoinServer(onion string) error {
|
||||||
return errors.New("no keys found for server connection")
|
return errors.New("no keys found for server connection")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResyncServer completely tears down and resyncs a new server connection with the given onion address
|
||||||
|
func (cp *cwtchPeer) ResyncServer(onion string) error {
|
||||||
|
if cp.GetContact(onion) != nil {
|
||||||
|
tokenY, yExists := cp.GetContact(onion).GetAttribute(string(model.KeyTypePrivacyPass))
|
||||||
|
tokenOnion, onionExists := cp.GetContact(onion).GetAttribute(string(model.KeyTypeTokenOnion))
|
||||||
|
if yExists && onionExists {
|
||||||
|
signature := base64.StdEncoding.EncodeToString([]byte{})
|
||||||
|
cp.eventBus.Publish(event.NewEvent(event.JoinServer, map[event.Field]string{event.GroupServer: onion, event.ServerTokenY: tokenY, event.ServerTokenOnion: tokenOnion, event.Signature: signature}))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.New("no keys found for server connection")
|
||||||
|
}
|
||||||
|
|
||||||
// SendMessageToGroupTracked attempts to sent the given message to the given group id.
|
// SendMessageToGroupTracked attempts to sent the given message to the given group id.
|
||||||
// It returns the signature of the message which can be used to identify it in any UX layer.
|
// It returns the signature of the message which can be used to identify it in any UX layer.
|
||||||
func (cp *cwtchPeer) SendMessageToGroupTracked(groupid string, message string) (string, error) {
|
func (cp *cwtchPeer) SendMessageToGroupTracked(groupid string, message string) (string, error) {
|
||||||
|
@ -546,19 +563,19 @@ func (cp *cwtchPeer) RejectInvite(groupID string) {
|
||||||
func (cp *cwtchPeer) Listen() {
|
func (cp *cwtchPeer) Listen() {
|
||||||
cp.mutex.Lock()
|
cp.mutex.Lock()
|
||||||
defer cp.mutex.Unlock()
|
defer cp.mutex.Unlock()
|
||||||
if cp.listenStatus == false {
|
if !cp.listenStatus {
|
||||||
log.Infof("cwtchPeer Listen sending ProtocolEngineStartListen\n")
|
log.Infof("cwtchPeer Listen sending ProtocolEngineStartListen\n")
|
||||||
cp.listenStatus = true
|
cp.listenStatus = true
|
||||||
cp.eventBus.Publish(event.NewEvent(event.ProtocolEngineStartListen, map[event.Field]string{event.Onion: cp.Profile.Onion}))
|
cp.eventBus.Publish(event.NewEvent(event.ProtocolEngineStartListen, map[event.Field]string{event.Onion: cp.Profile.Onion}))
|
||||||
} else {
|
|
||||||
// protocol engine is already listening
|
|
||||||
}
|
}
|
||||||
|
// else protocol engine is already listening
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartPeersConnections attempts to connect to peer connections
|
// StartPeersConnections attempts to connect to peer connections
|
||||||
func (cp *cwtchPeer) StartPeersConnections() {
|
func (cp *cwtchPeer) StartPeersConnections() {
|
||||||
for _, contact := range cp.GetContacts() {
|
for _, contact := range cp.GetContacts() {
|
||||||
if cp.GetContact(contact).IsServer() == false {
|
if !cp.GetContact(contact).IsServer() {
|
||||||
cp.PeerWithOnion(contact)
|
cp.PeerWithOnion(contact)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -684,7 +701,14 @@ func (cp *cwtchPeer) eventHandler() {
|
||||||
|
|
||||||
ciphertext, _ := base64.StdEncoding.DecodeString(ev.Data[event.Ciphertext])
|
ciphertext, _ := base64.StdEncoding.DecodeString(ev.Data[event.Ciphertext])
|
||||||
signature, _ := base64.StdEncoding.DecodeString(ev.Data[event.Signature])
|
signature, _ := base64.StdEncoding.DecodeString(ev.Data[event.Signature])
|
||||||
|
|
||||||
|
// SECURITY NOTE: A malicious server could insert posts such that everyone always has a different lastKnownSignature
|
||||||
|
// However the server can always replace **all** messages in an attempt to track users
|
||||||
|
// This is mitigated somewhat by resync events which do wipe things entire.
|
||||||
|
// The security of cwtch groups are also not dependent on the servers inability to uniquely tag connections (as long as
|
||||||
|
// it learns nothing else about each connection).
|
||||||
cp.SetContactAttribute(ev.Data[event.GroupServer], lastKnownSignature, ev.Data[event.Signature])
|
cp.SetContactAttribute(ev.Data[event.GroupServer], lastKnownSignature, ev.Data[event.Signature])
|
||||||
|
|
||||||
cp.mutex.Lock()
|
cp.mutex.Lock()
|
||||||
ok, groupID, message, seen := cp.Profile.AttemptDecryption(ciphertext, signature)
|
ok, groupID, message, seen := cp.Profile.AttemptDecryption(ciphertext, signature)
|
||||||
cp.mutex.Unlock()
|
cp.mutex.Unlock()
|
||||||
|
|
|
@ -27,9 +27,6 @@ type engine struct {
|
||||||
identity primitives.Identity
|
identity primitives.Identity
|
||||||
acn connectivity.ACN
|
acn connectivity.ACN
|
||||||
|
|
||||||
// Engine State
|
|
||||||
started bool
|
|
||||||
|
|
||||||
// Authorization list of contacts to authorization status
|
// Authorization list of contacts to authorization status
|
||||||
authorizations sync.Map // string(onion) => model.Authorization
|
authorizations sync.Map // string(onion) => model.Authorization
|
||||||
|
|
||||||
|
@ -136,12 +133,7 @@ func (e *engine) eventHandler() {
|
||||||
}
|
}
|
||||||
go e.peerWithTokenServer(ev.Data[event.GroupServer], ev.Data[event.ServerTokenOnion], ev.Data[event.ServerTokenY], signature)
|
go e.peerWithTokenServer(ev.Data[event.GroupServer], ev.Data[event.ServerTokenOnion], ev.Data[event.ServerTokenY], signature)
|
||||||
case event.LeaveServer:
|
case event.LeaveServer:
|
||||||
es, ok := e.ephemeralServices.Load(ev.Data[event.GroupServer])
|
e.leaveServer(ev.Data[event.GroupServer])
|
||||||
if ok {
|
|
||||||
ephemeralService := es.(tapir.Service)
|
|
||||||
ephemeralService.Shutdown()
|
|
||||||
e.ephemeralServices.Delete(ev.Data[event.GroupServer])
|
|
||||||
}
|
|
||||||
case event.DeleteContact:
|
case event.DeleteContact:
|
||||||
onion := ev.Data[event.RemotePeer]
|
onion := ev.Data[event.RemotePeer]
|
||||||
// We remove this peer from out blocklist which will prevent them from contacting us if we have "block unknown peers" turned on.
|
// We remove this peer from out blocklist which will prevent them from contacting us if we have "block unknown peers" turned on.
|
||||||
|
@ -234,7 +226,6 @@ func (e *engine) listenFn() {
|
||||||
if !e.shuttingDown {
|
if !e.shuttingDown {
|
||||||
e.eventManager.Publish(event.NewEvent(event.ProtocolEngineStopped, map[event.Field]string{event.Identity: e.identity.Hostname(), event.Error: err.Error()}))
|
e.eventManager.Publish(event.NewEvent(event.ProtocolEngineStopped, map[event.Field]string{event.Identity: e.identity.Hostname(), event.Error: err.Error()}))
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown tears down the eventHandler goroutine
|
// Shutdown tears down the eventHandler goroutine
|
||||||
|
@ -279,9 +270,14 @@ func (e *engine) peerWithTokenServer(onion string, tokenServerOnion string, toke
|
||||||
if exists {
|
if exists {
|
||||||
connection := service.(*tor.BaseOnionService)
|
connection := service.(*tor.BaseOnionService)
|
||||||
if conn, err := connection.GetConnection(onion); err == nil {
|
if conn, err := connection.GetConnection(onion); err == nil {
|
||||||
if conn.IsClosed() == false {
|
// We are already peered and synced so return...
|
||||||
|
// This will only not-trigger it lastKnownSignature has been wiped, which only happens when ResyncServer is called
|
||||||
|
// in CwtchPeer.
|
||||||
|
if !conn.IsClosed() && len(lastKnownSignature) != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Otherwise...we are going to rebuild the connection(which will result in a bandwidth heavy resync)...
|
||||||
|
e.leaveServer(onion)
|
||||||
}
|
}
|
||||||
// Otherwise...let's reconnect
|
// Otherwise...let's reconnect
|
||||||
}
|
}
|
||||||
|
@ -454,12 +450,12 @@ func (e *engine) sendMessageToGroup(groupID string, server string, ct []byte, si
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tokenApp, ok := (conn.App()).(*TokenBoardClient)
|
tokenApp, ok := (conn.App()).(*TokenBoardClient)
|
||||||
if ok {
|
if ok {
|
||||||
if spent, numtokens := tokenApp.Post(ct, sig); spent == false {
|
if spent, numtokens := tokenApp.Post(ct, sig); !spent {
|
||||||
// TODO: while this works for the spam guard, it won't work for other forms of payment...
|
// TODO: while this works for the spam guard, it won't work for other forms of payment...
|
||||||
// Make an -inline- payment, this will hold the goroutine
|
// Make an -inline- payment, this will hold the goroutine
|
||||||
if err := tokenApp.MakePayment(); err == nil {
|
if err := tokenApp.MakePayment(); err == nil {
|
||||||
// This really shouldn't fail since we now know we have the required tokens...
|
// This really shouldn't fail since we now know we have the required tokens...
|
||||||
if spent, _ := tokenApp.Post(ct, sig); spent == false {
|
if spent, _ := tokenApp.Post(ct, sig); !spent {
|
||||||
e.eventManager.Publish(event.NewEvent(event.SendMessageToGroupError, map[event.Field]string{event.GroupID: groupID, event.GroupServer: server, event.Error: err.Error(), event.Signature: base64.StdEncoding.EncodeToString(sig)}))
|
e.eventManager.Publish(event.NewEvent(event.SendMessageToGroupError, map[event.Field]string{event.GroupID: groupID, event.GroupServer: server, event.Error: err.Error(), event.Signature: base64.StdEncoding.EncodeToString(sig)}))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -508,3 +504,12 @@ func (e *engine) handlePeerRetVal(hostname string, getValData, retValData []byte
|
||||||
|
|
||||||
e.eventManager.Publish(event.NewEventList(event.NewRetValMessageFromPeer, event.RemotePeer, hostname, event.Scope, getVal.Scope, event.Path, getVal.Path, event.Exists, strconv.FormatBool(retVal.Exists), event.Data, retVal.Val))
|
e.eventManager.Publish(event.NewEventList(event.NewRetValMessageFromPeer, event.RemotePeer, hostname, event.Scope, getVal.Scope, event.Path, getVal.Path, event.Exists, strconv.FormatBool(retVal.Exists), event.Data, retVal.Val))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *engine) leaveServer(server string) {
|
||||||
|
es, ok := e.ephemeralServices.Load(server)
|
||||||
|
if ok {
|
||||||
|
ephemeralService := es.(tapir.Service)
|
||||||
|
ephemeralService.Shutdown()
|
||||||
|
e.ephemeralServices.Delete(server)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -167,8 +167,7 @@ func (ta *TokenBoardClient) Post(ct []byte, sig []byte) (bool, int) {
|
||||||
func (ta *TokenBoardClient) MakePayment() error {
|
func (ta *TokenBoardClient) MakePayment() error {
|
||||||
log.Debugf("Making a Payment %v", ta)
|
log.Debugf("Making a Payment %v", ta)
|
||||||
id, sk := primitives.InitializeEphemeralIdentity()
|
id, sk := primitives.InitializeEphemeralIdentity()
|
||||||
var client tapir.Service
|
client := new(tor.BaseOnionService)
|
||||||
client = new(tor.BaseOnionService)
|
|
||||||
client.Init(ta.acn, sk, &id)
|
client.Init(ta.acn, sk, &id)
|
||||||
|
|
||||||
tokenApplication := new(applications.TokenApplication)
|
tokenApplication := new(applications.TokenApplication)
|
||||||
|
@ -202,7 +201,7 @@ func (ta *TokenBoardClient) NextToken(data []byte, hostname string) (privacypass
|
||||||
ta.tokenLock.Lock()
|
ta.tokenLock.Lock()
|
||||||
defer ta.tokenLock.Unlock()
|
defer ta.tokenLock.Unlock()
|
||||||
if len(ta.tokens) == 0 {
|
if len(ta.tokens) == 0 {
|
||||||
return privacypass.SpentToken{}, len(ta.tokens), errors.New("No more tokens")
|
return privacypass.SpentToken{}, len(ta.tokens), errors.New("no more tokens")
|
||||||
}
|
}
|
||||||
token := ta.tokens[0]
|
token := ta.tokens[0]
|
||||||
ta.tokens = ta.tokens[1:]
|
ta.tokens = ta.tokens[1:]
|
||||||
|
|
Loading…
Reference in New Issue