mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-22 23:41:35 +00:00
don't have Conn.Read return an error for temorary crypto failures from e.g. out of order packets, just drop the packet and keep blocking until there's usable traffic
This commit is contained in:
parent
7e837e97e9
commit
1addf08ccd
@ -191,59 +191,64 @@ func (c *Conn) Read(b []byte) (int, error) {
|
|||||||
return 0, errors.New("search failed")
|
return 0, errors.New("search failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Wait for some traffic to come through from the session
|
for {
|
||||||
select {
|
// Wait for some traffic to come through from the session
|
||||||
case <-timer.C:
|
select {
|
||||||
return 0, ConnError{errors.New("timeout"), true, false, 0}
|
|
||||||
case p, ok := <-sinfo.recv:
|
|
||||||
// If the session is closed then do nothing
|
|
||||||
if !ok {
|
|
||||||
return 0, errors.New("session is closed")
|
|
||||||
}
|
|
||||||
defer util.PutBytes(p.Payload)
|
|
||||||
var err error
|
|
||||||
done := make(chan struct{})
|
|
||||||
workerFunc := func() {
|
|
||||||
defer close(done)
|
|
||||||
// If the nonce is bad then drop the packet and return an error
|
|
||||||
if !sinfo.nonceIsOK(&p.Nonce) {
|
|
||||||
err = ConnError{errors.New("packet dropped due to invalid nonce"), false, true, 0}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Decrypt the packet
|
|
||||||
bs, isOK := crypto.BoxOpen(&sinfo.sharedSesKey, p.Payload, &p.Nonce)
|
|
||||||
defer util.PutBytes(bs) // FIXME commenting this out leads to illegal buffer reuse, this implies there's a memory error somewhere and that this is just flooding things out of the finite pool of old slices that get reused
|
|
||||||
// Check if we were unable to decrypt the packet for some reason and
|
|
||||||
// return an error if we couldn't
|
|
||||||
if !isOK {
|
|
||||||
err = errors.New("packet dropped due to decryption failure")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Return the newly decrypted buffer back to the slice we were given
|
|
||||||
copy(b, bs)
|
|
||||||
// Trim the slice down to size based on the data we received
|
|
||||||
if len(bs) < len(b) {
|
|
||||||
b = b[:len(bs)]
|
|
||||||
}
|
|
||||||
// Update the session
|
|
||||||
sinfo.updateNonce(&p.Nonce)
|
|
||||||
sinfo.time = time.Now()
|
|
||||||
sinfo.bytesRecvd += uint64(len(b))
|
|
||||||
}
|
|
||||||
// Hand over to the session worker
|
|
||||||
select { // Send to worker
|
|
||||||
case sinfo.worker <- workerFunc:
|
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
return 0, ConnError{errors.New("timeout"), true, false, 0}
|
return 0, ConnError{errors.New("timeout"), true, false, 0}
|
||||||
|
case p, ok := <-sinfo.recv:
|
||||||
|
// If the session is closed then do nothing
|
||||||
|
if !ok {
|
||||||
|
return 0, errors.New("session is closed")
|
||||||
|
}
|
||||||
|
defer util.PutBytes(p.Payload)
|
||||||
|
var err error
|
||||||
|
done := make(chan struct{})
|
||||||
|
workerFunc := func() {
|
||||||
|
defer close(done)
|
||||||
|
// If the nonce is bad then drop the packet and return an error
|
||||||
|
if !sinfo.nonceIsOK(&p.Nonce) {
|
||||||
|
err = ConnError{errors.New("packet dropped due to invalid nonce"), false, true, 0}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Decrypt the packet
|
||||||
|
bs, isOK := crypto.BoxOpen(&sinfo.sharedSesKey, p.Payload, &p.Nonce)
|
||||||
|
defer util.PutBytes(bs) // FIXME commenting this out leads to illegal buffer reuse, this implies there's a memory error somewhere and that this is just flooding things out of the finite pool of old slices that get reused
|
||||||
|
// Check if we were unable to decrypt the packet for some reason and
|
||||||
|
// return an error if we couldn't
|
||||||
|
if !isOK {
|
||||||
|
err = ConnError{errors.New("packet dropped due to decryption failure"), false, true, 0}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Return the newly decrypted buffer back to the slice we were given
|
||||||
|
copy(b, bs)
|
||||||
|
// Trim the slice down to size based on the data we received
|
||||||
|
if len(bs) < len(b) {
|
||||||
|
b = b[:len(bs)]
|
||||||
|
}
|
||||||
|
// Update the session
|
||||||
|
sinfo.updateNonce(&p.Nonce)
|
||||||
|
sinfo.time = time.Now()
|
||||||
|
sinfo.bytesRecvd += uint64(len(b))
|
||||||
|
}
|
||||||
|
// Hand over to the session worker
|
||||||
|
select { // Send to worker
|
||||||
|
case sinfo.worker <- workerFunc:
|
||||||
|
case <-timer.C:
|
||||||
|
return 0, ConnError{errors.New("timeout"), true, false, 0}
|
||||||
|
}
|
||||||
|
<-done // Wait for the worker to finish, failing this can cause memory errors (util.[Get||Put]Bytes stuff)
|
||||||
|
// Something went wrong in the session worker so abort
|
||||||
|
if err != nil {
|
||||||
|
if ce, ok := err.(*ConnError); ok && ce.Temporary() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
// If we've reached this point then everything went to plan, return the
|
||||||
|
// number of bytes we populated back into the given slice
|
||||||
|
return len(b), nil
|
||||||
}
|
}
|
||||||
<-done // Wait for the worker to finish, failing this can cause memory errors (util.[Get||Put]Bytes stuff)
|
|
||||||
// Something went wrong in the session worker so abort
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
// If we've reached this point then everything went to plan, return the
|
|
||||||
// number of bytes we populated back into the given slice
|
|
||||||
return len(b), nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user