}
func (e *Event) Fire() {
- if e == nil || atomic.SwapInt32(&e.guard, 1) != 0 {
+ if atomic.SwapInt32(&e.guard, 1) != 0 {
return
}
- now := time.Now()
- if e.next.After(now) {
+ if now := time.Now(); now.After(e.next) {
select {
case e.C <- struct{}{}:
default:
logger.Debug.Println("Debug log enabled")
-
if err != nil {
logger.Error.Println("Failed to create TUN device:", err)
os.Exit(ExitSetupFailed)
} else {
kp.previous = kp.current
kp.current = keyPair
- peer.signal.newKeyPair.Send()
+ peer.event.newKeyPair.Fire()
}
} else {
const (
PeerRoutineNumber = 4
- EventInterval = time.Millisecond
+ EventInterval = 10 * time.Millisecond
)
type Peer struct {
dataReceived *Event
anyAuthenticatedPacketReceived *Event
anyAuthenticatedPacketTraversal *Event
- handshakeComplete *Event
+ handshakeCompleted *Event
handshakePushDeadline *Event
+ handshakeBegin *Event
ephemeralKeyCreated *Event
+ newKeyPair *Event
}
signal struct {
- newKeyPair Signal // size 1, new key pair was generated
- handshakeCompleted Signal // size 1, handshake completed
- handshakeBegin Signal // size 1, begin new handshake begin
- messageSend Signal // size 1, message was send to peer
- messageReceived Signal // size 1, authenticated message recv
-
flushNonceQueue chan struct{} // size 0, empty queued packets
}
peer.device = device
peer.isRunning.Set(false)
+ // events
+
+ peer.event.dataSent = newEvent(EventInterval)
+ peer.event.dataReceived = newEvent(EventInterval)
+ peer.event.anyAuthenticatedPacketReceived = newEvent(EventInterval)
+ peer.event.anyAuthenticatedPacketTraversal = newEvent(EventInterval)
+ peer.event.handshakeCompleted = newEvent(EventInterval)
+ peer.event.handshakePushDeadline = newEvent(EventInterval)
+ peer.event.handshakeBegin = newEvent(EventInterval)
+ peer.event.ephemeralKeyCreated = newEvent(EventInterval)
+ peer.event.newKeyPair = newEvent(EventInterval)
+
// map public key
_, ok := device.peers.keyMap[pk]
peer.routines.starting.Wait()
peer.routines.stopping.Wait()
- // events
-
- peer.event.dataSent = newEvent(EventInterval)
- peer.event.dataReceived = newEvent(EventInterval)
- peer.event.anyAuthenticatedPacketReceived = newEvent(EventInterval)
- peer.event.anyAuthenticatedPacketTraversal = newEvent(EventInterval)
- peer.event.handshakeComplete = newEvent(EventInterval)
- peer.event.handshakePushDeadline = newEvent(EventInterval)
- peer.event.ephemeralKeyCreated = newEvent(EventInterval)
-
// prepare queues and signals
- peer.signal.newKeyPair = NewSignal()
- peer.signal.handshakeBegin = NewSignal()
- peer.signal.handshakeCompleted = NewSignal()
-
peer.signal.flushNonceQueue = make(chan struct{})
peer.queue.nonce = make(chan *QueueOutboundElement, QueueOutboundSize)
// close signals
- peer.signal.newKeyPair.Close()
- peer.signal.handshakeBegin.Close()
- peer.signal.handshakeCompleted.Close()
-
close(peer.signal.flushNonceQueue)
-
peer.signal.flushNonceQueue = nil
// clear key pairs
// update timers
- peer.TimerAnyAuthenticatedPacketTraversal()
- peer.TimerAnyAuthenticatedPacketReceived()
+ peer.event.anyAuthenticatedPacketTraversal.Fire()
+ peer.event.anyAuthenticatedPacketReceived.Fire()
// update endpoint
err = peer.SendBuffer(packet)
if err == nil {
- peer.TimerAnyAuthenticatedPacketTraversal()
+ peer.event.anyAuthenticatedPacketTraversal.Fire()
} else {
logError.Println(peer, ": Failed to send handshake response", err)
}
// update timers
- peer.TimerAnyAuthenticatedPacketTraversal()
- peer.TimerAnyAuthenticatedPacketReceived()
- peer.TimerHandshakeComplete()
+ peer.event.anyAuthenticatedPacketTraversal.Fire()
+ peer.event.anyAuthenticatedPacketReceived.Fire()
+ peer.event.handshakeCompleted.Fire()
// derive key-pair
continue
}
- peer.TimerAnyAuthenticatedPacketTraversal()
- peer.TimerAnyAuthenticatedPacketReceived()
+ peer.event.anyAuthenticatedPacketTraversal.Fire()
+ peer.event.anyAuthenticatedPacketReceived.Fire()
peer.KeepKeyFreshReceiving()
// check if using new key-pair
kp := &peer.keyPairs
kp.mutex.Lock()
if kp.next == elem.keyPair {
- peer.TimerHandshakeComplete()
+ peer.event.handshakeCompleted.Fire()
if kp.previous != nil {
device.DeleteKeyPair(kp.previous)
}
logDebug.Println(peer, ": Received keep-alive")
continue
}
- peer.TimerDataReceived()
+ peer.event.dataReceived.Fire()
// verify source and strip padding
// wait for key pair
for {
+
+ peer.event.newKeyPair.Clear()
+
keyPair = peer.keyPairs.Current()
if keyPair != nil && keyPair.sendNonce < RejectAfterMessages {
if time.Now().Sub(keyPair.created) < RejectAfterTime {
}
}
- peer.signal.handshakeBegin.Send()
+ peer.event.handshakeBegin.Fire()
logDebug.Println(peer, ": Awaiting key-pair")
select {
- case <-peer.signal.newKeyPair.Wait():
+ case <-peer.event.newKeyPair.C:
logDebug.Println(peer, ": Obtained awaited key-pair")
case <-peer.signal.flushNonceQueue:
goto NextPacket
// update timers
- peer.TimerAnyAuthenticatedPacketTraversal()
+ peer.event.anyAuthenticatedPacketTraversal.Fire()
if len(elem.packet) != MessageKeepaliveSize {
- peer.TimerDataSent()
+ peer.event.dataSent.Fire()
}
peer.KeepKeyFreshSending()
}
}
nonce := atomic.LoadUint64(&kp.sendNonce)
if nonce > RekeyAfterMessages {
- peer.signal.handshakeBegin.Send()
+ peer.event.handshakeBegin.Fire()
}
if kp.isInitiator && time.Now().Sub(kp.created) > RekeyAfterTime {
- peer.signal.handshakeBegin.Send()
+ peer.event.handshakeBegin.Fire()
}
}
if send {
// do a last minute attempt at initiating a new handshake
peer.timer.sendLastMinuteHandshake.Set(true)
- peer.signal.handshakeBegin.Send()
+ peer.event.handshakeBegin.Fire()
}
}
}
}
-/* Event:
- * Sent non-empty (authenticated) transport message
- */
-func (peer *Peer) TimerDataSent() {
- peer.event.dataSent.Fire()
-}
-
-/* Event:
- * Received non-empty (authenticated) transport message
- *
- * Action:
- * Set a timer to confirm the message using a keep-alive (if not already set)
- */
-func (peer *Peer) TimerDataReceived() {
- peer.event.dataReceived.Fire()
- /*
- if !peer.timer.keepalivePassive.Start(KeepaliveTimeout) {
- peer.timer.needAnotherKeepalive.Set(true)
- }
- */
-}
-
-/* Event:
- * Any (authenticated) packet received
- */
-func (peer *Peer) TimerAnyAuthenticatedPacketReceived() {
- peer.event.anyAuthenticatedPacketReceived.Fire()
-}
-
-/* Event:
- * Any authenticated packet send / received.
- *
- * Action:
- * Push persistent keep-alive into the future
- */
-func (peer *Peer) TimerAnyAuthenticatedPacketTraversal() {
- peer.event.anyAuthenticatedPacketTraversal.Fire()
-}
-
/* Called after successfully completing a handshake.
* i.e. after:
*
* - Valid handshake response
* - First transport message under the "next" key
*/
-func (peer *Peer) TimerHandshakeComplete() {
- peer.signal.handshakeCompleted.Send()
- peer.device.log.Info.Println(peer, ": New handshake completed")
-}
+// peer.device.log.Info.Println(peer, ": New handshake completed")
/* Event:
* An ephemeral key is generated
*/
func (peer *Peer) sendNewHandshake() error {
- // temporarily disable the handshake complete signal
-
- peer.signal.handshakeCompleted.Disable()
-
// create initiation message
msg, err := peer.device.CreateMessageInitiation(peer)
// send to endpoint
- peer.TimerAnyAuthenticatedPacketTraversal()
-
- err = peer.SendBuffer(packet)
- if err == nil {
- peer.signal.handshakeCompleted.Enable()
- }
+ peer.event.anyAuthenticatedPacketTraversal.Fire()
- return err
+ return peer.SendBuffer(packet)
}
func newTimer() *time.Timer {
// reset all timers
+ enableHandshake := true
+
pendingHandshakeNew := false
pendingKeepalivePassive := false
// handshake timers
- case <-timerHandshakeNew.C:
- logInfo.Println(peer, ": Retrying handshake (timer event)")
- peer.signal.handshakeBegin.Send()
-
case <-timerHandshakeTimeout.C:
+ // allow new handshake to be send
+
+ enableHandshake = true
+
// clear source (in case this is causing problems)
peer.mutex.Lock()
logDebug.Println(peer, ": Send handshake initiation (subsequent)")
}
+ // disable further handshakes
+
+ peer.event.handshakeBegin.Clear()
+ enableHandshake = false
+
case <-timerHandshakeDeadline.C:
// clear all queued packets and stop keep-alive
peer.flushNonceQueue()
signalSend(peer.signal.flushNonceQueue)
timerKeepalivePersistent.Stop()
- peer.signal.handshakeBegin.Enable()
- /* signals */
+ // disable further handshakes
+
+ peer.event.handshakeBegin.Clear()
+ enableHandshake = true
- case <-peer.signal.handshakeBegin.Wait():
+ case <-peer.event.handshakeBegin.C:
+
+ if !enableHandshake {
+ continue
+ }
- peer.signal.handshakeBegin.Disable()
+ logDebug.Println(peer, ": Event, Handshake Begin")
err := peer.sendNewHandshake()
timerHandshakeDeadline.Reset(RekeyAttemptTime)
- case <-peer.signal.handshakeCompleted.Wait():
+ // disable further handshakes
+
+ peer.event.handshakeBegin.Clear()
+ enableHandshake = false
+
+ case <-peer.event.handshakeCompleted.C:
logInfo.Println(peer, ": Handshake completed")
timerHandshakeTimeout.Stop()
timerHandshakeDeadline.Stop()
- peer.signal.handshakeBegin.Enable()
-
peer.timer.sendLastMinuteHandshake.Set(false)
+
+ // allow further handshakes
+
+ peer.event.handshakeBegin.Clear()
+ enableHandshake = true
}
}
}