Actively Deduplicate Connections on WaitForCapabilityOrClose #40
|
@ -10,7 +10,6 @@ import (
|
||||||
"git.openprivacy.ca/openprivacy/log"
|
"git.openprivacy.ca/openprivacy/log"
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseOnionService is a concrete implementation of the service interface over Tor onion services.
|
// BaseOnionService is a concrete implementation of the service interface over Tor onion services.
|
||||||
|
@ -66,16 +65,36 @@ func (s *BaseOnionService) WaitForCapabilityOrClose(cid string, name tapir.Capab
|
||||||
conn, err := s.GetConnection(cid)
|
conn, err := s.GetConnection(cid)
|
||||||
// If there is at least one active connection, then check the one that is returned and use it
|
// If there is at least one active connection, then check the one that is returned and use it
|
||||||
for conn != nil {
|
for conn != nil {
|
||||||
if conn.HasCapability(name) {
|
|
||||||
|
// if we have only one and it has the right capability then return
|
||||||
|
if conn.HasCapability(name) && err == nil {
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
time.Sleep(time.Millisecond * 200)
|
|
||||||
// If we received both a Connection and an Error from GetConnection that means we have multiple connections
|
// If We have 2 connections for the same hostname...
|
||||||
// If that was the case we refresh from the connection store as the likely case is one of them has been
|
|
||||||
// closed and the other one has the capabilities we need.
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn, err = s.GetConnection(cid)
|
log.Debugf("found duplicate connections for %v <-> %v", s.id.Hostname(), cid)
|
||||||
|
// By convention the lowest lexicographical hostname purges all their outbounds to the higher
|
||||||
|
// hostname
|
||||||
|
// Which should only leave a single connection remaining (as we dedupe on connect too)
|
||||||
|
// This does allow people to attempt to guarantee being the outbound connection but due to the bidirectional
|
||||||
|
// authentication this should never result in an advantage in the protocol.
|
||||||
|
if s.id.Hostname() < cid {
|
||||||
|
// Close all output connections to connection
|
||||||
|
s.connections.Range(func(key, value interface{}) bool {
|
||||||
|
connection := value.(tapir.Connection)
|
||||||
|
if connection.Hostname() == cid {
|
||||||
|
if !connection.IsClosed() && connection.IsOutbound() {
|
||||||
|
connection.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We had a connection but it didn't have a cpability...try again
|
||||||
|
conn, err = s.GetConnection(cid)
|
||||||
}
|
}
|
||||||
// There are no active connections with that hostname
|
// There are no active connections with that hostname
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
Loading…
Reference in New Issue