}
func (e *Event) Fire() {
- if atomic.SwapInt32(&e.guard, 1) != 0 {
+ if e == nil || atomic.SwapInt32(&e.guard, 1) != 0 {
return
}
if now := time.Now(); now.After(e.next) {
}
func warning() {
- shouldQuit := false
-
fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING")
fmt.Fprintln(os.Stderr, "W G")
fmt.Fprintln(os.Stderr, "W This is alpha software. It will very likely not G")
fmt.Fprintln(os.Stderr, "W horribly wrong. You have been warned. Proceed G")
fmt.Fprintln(os.Stderr, "W at your own risk. G")
if runtime.GOOS == "linux" {
- shouldQuit = os.Getenv("WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD") != "1"
-
fmt.Fprintln(os.Stderr, "W G")
fmt.Fprintln(os.Stderr, "W Furthermore, you are running this software on a G")
fmt.Fprintln(os.Stderr, "W Linux kernel, which is probably unnecessary and G")
fmt.Fprintln(os.Stderr, "W program. For more information on installing the G")
fmt.Fprintln(os.Stderr, "W kernel module, please visit: G")
fmt.Fprintln(os.Stderr, "W https://www.wireguard.com/install G")
- if shouldQuit {
- fmt.Fprintln(os.Stderr, "W G")
- fmt.Fprintln(os.Stderr, "W If you still want to use this program, against G")
- fmt.Fprintln(os.Stderr, "W the sage advice here, please first export this G")
- fmt.Fprintln(os.Stderr, "W environment variable: G")
- fmt.Fprintln(os.Stderr, "W WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD=1 G")
- }
}
fmt.Fprintln(os.Stderr, "W G")
fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING")
-
- if shouldQuit {
- os.Exit(1)
- }
}
func main() {
handshakeBegin *Event
ephemeralKeyCreated *Event
newKeyPair *Event
- }
-
- signal struct {
- flushNonceQueue chan struct{} // size 0, empty queued packets
+ flushNonceQueue *Event
}
timer struct {
sendLastMinuteHandshake AtomicBool
- needAnotherKeepalive AtomicBool
}
queue struct {
mutex sync.Mutex // held when stopping / starting routines
starting sync.WaitGroup // routines pending start
stopping sync.WaitGroup // routines pending stop
- stop Signal // size 0, stop all go-routines in peer
+ stop chan struct{} // size 0, stop all go-routines in peer
}
mac CookieGenerator
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.endpoint = nil
- // prepare signaling & routines
-
- peer.routines.mutex.Lock()
- peer.routines.stop = NewSignal()
- peer.routines.mutex.Unlock()
-
// start peer
if peer.device.isUp.Get() {
device := peer.device
device.log.Debug.Println(peer, ": Starting...")
- // sanity check : these should be 0
+ // reset routine state
peer.routines.starting.Wait()
peer.routines.stopping.Wait()
+ peer.routines.stop = make(chan struct{})
- // prepare queues and signals
-
- peer.signal.flushNonceQueue = make(chan struct{})
+ // prepare queues
peer.queue.nonce = make(chan *QueueOutboundElement, QueueOutboundSize)
peer.queue.outbound = make(chan *QueueOutboundElement, QueueOutboundSize)
peer.queue.inbound = make(chan *QueueInboundElement, QueueInboundSize)
- peer.routines.stop = NewSignal()
+ // 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)
+ peer.event.flushNonceQueue = newEvent(EventInterval)
+
peer.isRunning.Set(true)
// wait for routines to start
// stop & wait for ongoing peer routines
peer.routines.starting.Wait()
- peer.routines.stop.Broadcast()
+ close(peer.routines.stop)
peer.routines.stopping.Wait()
// close queues
close(peer.queue.outbound)
close(peer.queue.inbound)
- // close signals
-
- close(peer.signal.flushNonceQueue)
- peer.signal.flushNonceQueue = nil
-
// clear key pairs
kp := &peer.keyPairs
select {
- case <-peer.routines.stop.Wait():
+ case <-peer.routines.stop:
return
case elem, ok := <-peer.queue.inbound:
for {
NextPacket:
+
+ peer.event.flushNonceQueue.Clear()
+
select {
- case <-peer.routines.stop.Wait():
+ case <-peer.routines.stop:
return
case elem, ok := <-peer.queue.nonce:
select {
case <-peer.event.newKeyPair.C:
logDebug.Println(peer, ": Obtained awaited key-pair")
- case <-peer.signal.flushNonceQueue:
+ case <-peer.event.flushNonceQueue.C:
goto NextPacket
- case <-peer.routines.stop.Wait():
+ case <-peer.routines.stop:
return
}
}
for {
select {
- case <-peer.routines.stop.Wait():
+ case <-peer.routines.stop:
return
case elem, ok := <-peer.queue.outbound:
// reset all timers
enableHandshake := true
-
pendingHandshakeNew := false
pendingKeepalivePassive := false
+ needAnotherKeepalive := false
timerKeepalivePassive := newTimer()
timerHandshakeDeadline := newTimer()
/* stopping */
- case <-peer.routines.stop.Wait():
+ case <-peer.routines.stop:
return
/* events */
case <-peer.event.dataReceived.C:
if pendingKeepalivePassive {
- peer.timer.needAnotherKeepalive.Set(true) // TODO: make local
+ needAnotherKeepalive = true
} else {
timerKeepalivePassive.Reset(KeepaliveTimeout)
}
/* timers */
- // keep-alive
-
case <-timerKeepalivePersistent.C:
interval := peer.persistentKeepaliveInterval
peer.SendKeepAlive()
- if peer.timer.needAnotherKeepalive.Swap(false) {
+ if needAnotherKeepalive {
timerKeepalivePassive.Reset(KeepaliveTimeout)
+ needAnotherKeepalive = false
}
- // clear key material timer
-
case <-timerZeroAllKeys.C:
logDebug.Println(peer, ": Clear all key-material (timer event)")
hs.Clear()
hs.mutex.Unlock()
- // handshake timers
-
case <-timerHandshakeTimeout.C:
// allow new handshake to be send
logInfo.Println(peer, ": Handshake negotiation timed-out")
peer.flushNonceQueue()
- signalSend(peer.signal.flushNonceQueue)
- timerKeepalivePersistent.Stop()
+ peer.event.flushNonceQueue.Fire()
- // disable further handshakes
+ // renable further handshakes
peer.event.handshakeBegin.Clear()
enableHandshake = true
-
}
}
}
return &IPCError{Code: ipcErrorInvalid}
}
+ peer.event.handshakePushDeadline.Fire()
+
case "endpoint":
// set endpoint destination