// synchronized resources (locks acquired in order)
state struct {
- starting sync.WaitGroup
stopping sync.WaitGroup
sync.Mutex
changing AtomicBool
}
net struct {
- starting sync.WaitGroup
stopping sync.WaitGroup
sync.RWMutex
bind conn.Bind // bind interface
// start workers
cpus := runtime.NumCPU()
- device.state.starting.Wait()
device.state.stopping.Wait()
for i := 0; i < cpus; i += 1 {
- device.state.starting.Add(3)
device.state.stopping.Add(3)
go device.RoutineEncryption()
go device.RoutineDecryption()
go device.RoutineHandshake()
}
- device.state.starting.Add(2)
device.state.stopping.Add(2)
go device.RoutineReadFromTUN()
go device.RoutineTUNEventReader()
- device.state.starting.Wait()
-
return device
}
return
}
- device.state.starting.Wait()
-
device.log.Info.Println("Device closing")
device.state.changing.Set(true)
device.state.Lock()
// start receiving routines
- device.net.starting.Add(2)
device.net.stopping.Add(2)
go device.RoutineReceiveIncoming(ipv4.Version, netc.bind)
go device.RoutineReceiveIncoming(ipv6.Version, netc.bind)
- device.net.starting.Wait()
device.log.Debug.Println("UDP bind has been updated")
}
}
routines struct {
- sync.Mutex // held when stopping / starting routines
- starting sync.WaitGroup // routines pending start
+ sync.Mutex // held when stopping routines
stopping sync.WaitGroup // routines pending stop
stop chan struct{} // size 0, stop all go routines in peer
}
// reset routine state
- peer.routines.starting.Wait()
peer.routines.stopping.Wait()
peer.routines.stop = make(chan struct{})
- peer.routines.starting.Add(PeerRoutineNumber)
peer.routines.stopping.Add(PeerRoutineNumber)
// prepare queues
go peer.RoutineSequentialSender()
go peer.RoutineSequentialReceiver()
- peer.routines.starting.Wait()
peer.isRunning.Set(true)
}
return
}
- peer.routines.starting.Wait()
-
peer.routines.Lock()
defer peer.routines.Unlock()
}()
logDebug.Println("Routine: receive incoming IPv" + strconv.Itoa(IP) + " - started")
- device.net.starting.Done()
// receive datagrams until conn is closed
device.state.stopping.Done()
}()
logDebug.Println("Routine: decryption worker - started")
- device.state.starting.Done()
for {
select {
}()
logDebug.Println("Routine: handshake worker - started")
- device.state.starting.Done()
for {
if elem.buffer != nil {
logDebug.Println(peer, "- Routine: sequential receiver - started")
- peer.routines.starting.Done()
-
for {
if elem != nil {
if !elem.IsDropped() {
}()
logDebug.Println("Routine: TUN reader - started")
- device.state.starting.Done()
var elem *QueueOutboundElement
peer.routines.stopping.Done()
}()
- peer.routines.starting.Done()
logDebug.Println(peer, "- Routine: nonce worker - started")
NextPacket:
}()
logDebug.Println("Routine: encryption worker - started")
- device.state.starting.Done()
for {
logDebug.Println(peer, "- Routine: sequential sender - started")
- peer.routines.starting.Done()
-
for {
select {
logError := device.log.Error
logDebug.Println("Routine: event worker - started")
- device.state.starting.Done()
for event := range device.tun.device.Events() {
if event&tun.EventMTUUpdate != 0 {