add some notion of priority to peers, default to 0, give connections that aren't an outgoing socks wrappedConn a higher priority, this should hopefully help to avoid using tor nodes as parents

This commit is contained in:
Arceliar 2018-12-01 12:03:38 -06:00
parent 05b07adba2
commit b2f394f4b6
3 changed files with 19 additions and 7 deletions

View file

@ -88,6 +88,7 @@ type peer struct {
endpoint string endpoint string
friendlyName string friendlyName string
firstSeen time.Time // To track uptime for getPeers firstSeen time.Time // To track uptime for getPeers
priority uint8 // Higher priority -> prefer as a parent in the tree
linkOut (chan []byte) // used for protocol traffic (to bypass queues) linkOut (chan []byte) // used for protocol traffic (to bypass queues)
doSend (chan struct{}) // tell the linkLoop to send a switchMsg doSend (chan struct{}) // tell the linkLoop to send a switchMsg
dinfo *dhtInfo // used to keep the DHT working dinfo *dhtInfo // used to keep the DHT working
@ -321,7 +322,7 @@ func (p *peer) handleSwitchMsg(packet []byte) {
} }
prevKey = hop.Next prevKey = hop.Next
} }
p.core.switchTable.handleMsg(&msg, p.port) p.core.switchTable.handleMsg(&msg, p.port, p.priority)
if !p.core.switchTable.checkRoot(&msg) { if !p.core.switchTable.checkRoot(&msg) {
// Bad switch message // Bad switch message
// Stop forwarding traffic from it // Stop forwarding traffic from it

View file

@ -125,6 +125,7 @@ type peerInfo struct {
time time.Time // Time this node was last seen time time.Time // Time this node was last seen
firstSeen time.Time firstSeen time.Time
port switchPort // Interface number of this peer port switchPort // Interface number of this peer
priority uint8 // Prefer to use nodes with a higher priority as a parent
msg switchMsg // The wire switchMsg used msg switchMsg // The wire switchMsg used
} }
@ -252,7 +253,7 @@ func (t *switchTable) forgetPeer(port switchPort) {
return return
} }
for _, info := range t.data.peers { for _, info := range t.data.peers {
t.unlockedHandleMsg(&info.msg, info.port) t.unlockedHandleMsg(&info.msg, info.port, info.priority)
} }
} }
@ -323,10 +324,10 @@ func (t *switchTable) checkRoot(msg *switchMsg) bool {
} }
// This is a mutexed wrapper to unlockedHandleMsg, and is called by the peer structs in peers.go to pass a switchMsg for that peer into the switch. // This is a mutexed wrapper to unlockedHandleMsg, and is called by the peer structs in peers.go to pass a switchMsg for that peer into the switch.
func (t *switchTable) handleMsg(msg *switchMsg, fromPort switchPort) { func (t *switchTable) handleMsg(msg *switchMsg, fromPort switchPort, priority uint8) {
t.mutex.Lock() t.mutex.Lock()
defer t.mutex.Unlock() defer t.mutex.Unlock()
t.unlockedHandleMsg(msg, fromPort) t.unlockedHandleMsg(msg, fromPort, priority)
} }
// This updates the switch with information about a peer. // This updates the switch with information about a peer.
@ -334,7 +335,7 @@ func (t *switchTable) handleMsg(msg *switchMsg, fromPort switchPort) {
// That happens if this node is already our parent, or is advertising a better root, or is advertising a better path to the same root, etc... // That happens if this node is already our parent, or is advertising a better root, or is advertising a better path to the same root, etc...
// There are a lot of very delicate order sensitive checks here, so its' best to just read the code if you need to understand what it's doing. // There are a lot of very delicate order sensitive checks here, so its' best to just read the code if you need to understand what it's doing.
// It's very important to not change the order of the statements in the case function unless you're absolutely sure that it's safe, including safe if used along side nodes that used the previous order. // It's very important to not change the order of the statements in the case function unless you're absolutely sure that it's safe, including safe if used along side nodes that used the previous order.
func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) { func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort, priority uint8) {
// TODO directly use a switchMsg instead of switchMessage + sigs // TODO directly use a switchMsg instead of switchMessage + sigs
now := time.Now() now := time.Now()
// Set up the sender peerInfo // Set up the sender peerInfo
@ -355,6 +356,7 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) {
} }
sender.firstSeen = oldSender.firstSeen sender.firstSeen = oldSender.firstSeen
sender.port = fromPort sender.port = fromPort
sender.priority = priority
sender.time = now sender.time = now
// Decide what to do // Decide what to do
equiv := func(x *switchLocator, y *switchLocator) bool { equiv := func(x *switchLocator, y *switchLocator) bool {
@ -420,6 +422,11 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) {
case noParent: case noParent:
// We currently have no working parent, and at this point in the switch statement, anything is better than nothing. // We currently have no working parent, and at this point in the switch statement, anything is better than nothing.
updateRoot = true updateRoot = true
case priority > oldParent.priority:
// We're supposed to prefer this node due to the kind of connection it is, e.g. direct instead of an outgoing socks connection.
updateRoot = true
case priority < oldParent.priority:
// We're supposed to avoid this node due to the kind of connection it is, e.g. an outgoing socks connection instead of direct.
case cost < pCost: case cost < pCost:
// The sender has a better combination of path length and reliability than the current parent. // The sender has a better combination of path length and reliability than the current parent.
updateRoot = true updateRoot = true
@ -432,9 +439,9 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) {
// Then reprocess *all* messages to look for a better parent. // Then reprocess *all* messages to look for a better parent.
// This is so we don't keep using this node as our parent if there's something better. // This is so we don't keep using this node as our parent if there's something better.
t.parent = 0 t.parent = 0
t.unlockedHandleMsg(msg, fromPort) t.unlockedHandleMsg(msg, fromPort, priority)
for _, info := range t.data.peers { for _, info := range t.data.peers {
t.unlockedHandleMsg(&info.msg, info.port) t.unlockedHandleMsg(&info.msg, info.port, info.priority)
} }
case now.Sub(t.time) < switch_throttle: case now.Sub(t.time) < switch_throttle:
// We've already gotten an update from this root recently, so ignore this one to avoid flooding. // We've already gotten an update from this root recently, so ignore this one to avoid flooding.

View file

@ -292,6 +292,10 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
in := func(bs []byte) { in := func(bs []byte) {
p.handlePacket(bs) p.handlePacket(bs)
} }
// Set priority
if _, isSocks := sock.(*wrappedConn); !isSocks {
p.priority = 1
}
out := make(chan []byte, 1) out := make(chan []byte, 1)
defer close(out) defer close(out)
go func() { go func() {