mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-12-24 16:57:53 +00:00
fix nil pointer deref if searches fail, block dial until a search exceeds or a timeout passes (todo: replace timer with context)
This commit is contained in:
parent
ca1f2bb0a2
commit
818eca90db
@ -89,11 +89,13 @@ func (c *Conn) search() error {
|
|||||||
<-done
|
<-done
|
||||||
c.session = sess
|
c.session = sess
|
||||||
if c.session == nil && err == nil {
|
if c.session == nil && err == nil {
|
||||||
panic("search failed but returend no error")
|
panic("search failed but returned no error")
|
||||||
}
|
}
|
||||||
c.nodeID = crypto.GetNodeID(&c.session.theirPermPub)
|
if c.session != nil {
|
||||||
for i := range c.nodeMask {
|
c.nodeID = crypto.GetNodeID(&c.session.theirPermPub)
|
||||||
c.nodeMask[i] = 0xFF
|
for i := range c.nodeMask {
|
||||||
|
c.nodeMask[i] = 0xFF
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
@ -218,8 +220,6 @@ func (c *Conn) Write(b []byte) (bytesWritten int, err error) {
|
|||||||
go func() { c.core.router.admin <- routerWork }()
|
go func() { c.core.router.admin <- routerWork }()
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case !sinfo.init:
|
|
||||||
sinfo.core.sessions.ping(sinfo)
|
|
||||||
case time.Since(sinfo.time) > 6*time.Second:
|
case time.Since(sinfo.time) > 6*time.Second:
|
||||||
if sinfo.time.Before(sinfo.pingTime) && time.Since(sinfo.pingTime) > 6*time.Second {
|
if sinfo.time.Before(sinfo.pingTime) && time.Since(sinfo.pingTime) > 6*time.Second {
|
||||||
// TODO double check that the above condition is correct
|
// TODO double check that the above condition is correct
|
||||||
@ -227,6 +227,8 @@ func (c *Conn) Write(b []byte) (bytesWritten int, err error) {
|
|||||||
} else {
|
} else {
|
||||||
sinfo.core.sessions.ping(sinfo)
|
sinfo.core.sessions.ping(sinfo)
|
||||||
}
|
}
|
||||||
|
case sinfo.reset && sinfo.pingTime.Before(sinfo.time):
|
||||||
|
sinfo.core.sessions.ping(sinfo)
|
||||||
default: // Don't do anything, to keep traffic throttled
|
default: // Don't do anything, to keep traffic throttled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
||||||
)
|
)
|
||||||
@ -61,7 +62,16 @@ func (d *Dialer) Dial(network, address string) (*Conn, error) {
|
|||||||
func (d *Dialer) DialByNodeIDandMask(nodeID, nodeMask *crypto.NodeID) (*Conn, error) {
|
func (d *Dialer) DialByNodeIDandMask(nodeID, nodeMask *crypto.NodeID) (*Conn, error) {
|
||||||
conn := newConn(d.core, nodeID, nodeMask, nil)
|
conn := newConn(d.core, nodeID, nodeMask, nil)
|
||||||
if err := conn.search(); err != nil {
|
if err := conn.search(); err != nil {
|
||||||
|
conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return conn, nil
|
t := time.NewTimer(6 * time.Second) // TODO use a context instead
|
||||||
|
defer t.Stop()
|
||||||
|
select {
|
||||||
|
case <-conn.session.init:
|
||||||
|
return conn, nil
|
||||||
|
case <-t.C:
|
||||||
|
conn.Close()
|
||||||
|
return nil, errors.New("session handshake timeout")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ func (r *router) mainLoop() {
|
|||||||
case info := <-r.core.dht.peers:
|
case info := <-r.core.dht.peers:
|
||||||
r.core.dht.insertPeer(info)
|
r.core.dht.insertPeer(info)
|
||||||
case <-r.reset:
|
case <-r.reset:
|
||||||
r.core.sessions.resetInits()
|
r.core.sessions.reset()
|
||||||
r.core.dht.reset()
|
r.core.dht.reset()
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
{
|
{
|
||||||
|
@ -39,12 +39,13 @@ type sessionInfo struct {
|
|||||||
pingTime time.Time // time the first ping was sent since the last received packet
|
pingTime time.Time // time the first ping was sent since the last received packet
|
||||||
pingSend time.Time // time the last ping was sent
|
pingSend time.Time // time the last ping was sent
|
||||||
coords []byte // coords of destination
|
coords []byte // coords of destination
|
||||||
init bool // Reset if coords change
|
reset bool // reset if coords change
|
||||||
tstamp int64 // ATOMIC - tstamp from their last session ping, replay attack mitigation
|
tstamp int64 // ATOMIC - tstamp from their last session ping, replay attack mitigation
|
||||||
bytesSent uint64 // Bytes of real traffic sent in this session
|
bytesSent uint64 // Bytes of real traffic sent in this session
|
||||||
bytesRecvd uint64 // Bytes of real traffic received in this session
|
bytesRecvd uint64 // Bytes of real traffic received in this session
|
||||||
worker chan func() // Channel to send work to the session worker
|
worker chan func() // Channel to send work to the session worker
|
||||||
recv chan *wire_trafficPacket // Received packets go here, picked up by the associated Conn
|
recv chan *wire_trafficPacket // Received packets go here, picked up by the associated Conn
|
||||||
|
init chan struct{} // Closed when the first session pong arrives, used to signal that the session is ready for initial use
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sinfo *sessionInfo) doWorker(f func()) {
|
func (sinfo *sessionInfo) doWorker(f func()) {
|
||||||
@ -101,7 +102,14 @@ func (s *sessionInfo) update(p *sessionPing) bool {
|
|||||||
}
|
}
|
||||||
s.time = time.Now()
|
s.time = time.Now()
|
||||||
s.tstamp = p.Tstamp
|
s.tstamp = p.Tstamp
|
||||||
s.init = true
|
s.reset = false
|
||||||
|
defer func() { recover() }() // Recover if the below panics
|
||||||
|
select {
|
||||||
|
case <-s.init:
|
||||||
|
default:
|
||||||
|
// Unblock anything waiting for the session to initialize
|
||||||
|
close(s.init)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +211,7 @@ func (ss *sessions) createSession(theirPermKey *crypto.BoxPubKey) *sessionInfo {
|
|||||||
sinfo.mtuTime = now
|
sinfo.mtuTime = now
|
||||||
sinfo.pingTime = now
|
sinfo.pingTime = now
|
||||||
sinfo.pingSend = now
|
sinfo.pingSend = now
|
||||||
|
sinfo.init = make(chan struct{})
|
||||||
higher := false
|
higher := false
|
||||||
for idx := range ss.core.boxPub {
|
for idx := range ss.core.boxPub {
|
||||||
if ss.core.boxPub[idx] > sinfo.theirPermPub[idx] {
|
if ss.core.boxPub[idx] > sinfo.theirPermPub[idx] {
|
||||||
@ -410,10 +419,10 @@ func (sinfo *sessionInfo) updateNonce(theirNonce *crypto.BoxNonce) {
|
|||||||
|
|
||||||
// Resets all sessions to an uninitialized state.
|
// Resets all sessions to an uninitialized state.
|
||||||
// Called after coord changes, so attemtps to use a session will trigger a new ping and notify the remote end of the coord change.
|
// Called after coord changes, so attemtps to use a session will trigger a new ping and notify the remote end of the coord change.
|
||||||
func (ss *sessions) resetInits() {
|
func (ss *sessions) reset() {
|
||||||
for _, sinfo := range ss.sinfos {
|
for _, sinfo := range ss.sinfos {
|
||||||
sinfo.doWorker(func() {
|
sinfo.doWorker(func() {
|
||||||
sinfo.init = false
|
sinfo.reset = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user