mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-28 22:25:07 +03:00
Squash a whole load of races (and mutex half the world)
This commit is contained in:
parent
24281d4049
commit
f3e742a297
4 changed files with 66 additions and 20 deletions
|
@ -3,6 +3,7 @@ package yggdrasil
|
|||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
|
@ -15,6 +16,7 @@ type Conn struct {
|
|||
nodeID *crypto.NodeID
|
||||
nodeMask *crypto.NodeID
|
||||
session *sessionInfo
|
||||
sessionMutex *sync.RWMutex
|
||||
readDeadline time.Time
|
||||
writeDeadline time.Time
|
||||
expired bool
|
||||
|
@ -28,7 +30,9 @@ func (c *Conn) startSearch() {
|
|||
return
|
||||
}
|
||||
if sinfo != nil {
|
||||
c.sessionMutex.Lock()
|
||||
c.session = sinfo
|
||||
c.sessionMutex.Unlock()
|
||||
}
|
||||
}
|
||||
doSearch := func() {
|
||||
|
@ -61,15 +65,20 @@ func (c *Conn) startSearch() {
|
|||
}
|
||||
|
||||
func (c *Conn) Read(b []byte) (int, error) {
|
||||
c.sessionMutex.RLock()
|
||||
defer c.sessionMutex.RUnlock()
|
||||
if c.expired {
|
||||
return 0, errors.New("session is closed")
|
||||
}
|
||||
if c.session == nil {
|
||||
return 0, errors.New("searching for remote side")
|
||||
}
|
||||
c.session.initMutex.RLock()
|
||||
if !c.session.init {
|
||||
c.session.initMutex.RUnlock()
|
||||
return 0, errors.New("waiting for remote side to accept")
|
||||
}
|
||||
c.session.initMutex.RUnlock()
|
||||
select {
|
||||
case p, ok := <-c.session.recv:
|
||||
if !ok {
|
||||
|
@ -93,7 +102,9 @@ func (c *Conn) Read(b []byte) (int, error) {
|
|||
b = b[:len(bs)]
|
||||
}
|
||||
c.session.updateNonce(&p.Nonce)
|
||||
c.session.timeMutex.Lock()
|
||||
c.session.time = time.Now()
|
||||
c.session.timeMutex.Unlock()
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
|
@ -108,6 +119,8 @@ func (c *Conn) Read(b []byte) (int, error) {
|
|||
}
|
||||
|
||||
func (c *Conn) Write(b []byte) (bytesWritten int, err error) {
|
||||
c.sessionMutex.RLock()
|
||||
defer c.sessionMutex.RUnlock()
|
||||
if c.expired {
|
||||
return 0, errors.New("session is closed")
|
||||
}
|
||||
|
@ -118,12 +131,16 @@ func (c *Conn) Write(b []byte) (bytesWritten int, err error) {
|
|||
return 0, errors.New("searching for remote side")
|
||||
}
|
||||
defer util.PutBytes(b)
|
||||
c.session.initMutex.RLock()
|
||||
if !c.session.init {
|
||||
// To prevent using empty session keys
|
||||
c.session.initMutex.RUnlock()
|
||||
return 0, errors.New("waiting for remote side to accept")
|
||||
}
|
||||
c.session.initMutex.RUnlock()
|
||||
// code isn't multithreaded so appending to this is safe
|
||||
c.session.coordsMutex.RLock()
|
||||
coords := c.session.coords
|
||||
c.session.coordsMutex.RUnlock()
|
||||
// Prepare the payload
|
||||
c.session.myNonceMutex.Lock()
|
||||
payload, nonce := crypto.BoxSeal(&c.session.sharedSesKey, b, &c.session.myNonce)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue