var (
bindAddr = flag.String("bind", "[::]:1194", "Bind to address")
peersPath = flag.String("peers", "peers", "Path to peers keys directory")
- mtu = flag.Int("mtu", 1500, "MTU")
- nonceDiff = flag.Int("noncediff", 1, "Allow nonce difference")
- timeoutP = flag.Int("timeout", 60, "Timeout seconds")
+ stats = flag.String("stats", "", "Enable stats retrieving on host:port")
+ mtu = flag.Int("mtu", 1452, "MTU for outgoing packets")
)
type PeerReadyEvent struct {
}
func NewPeerState(peer *govpn.Peer, iface string) *PeerState {
- tap, sink, ready, terminate, err := govpn.TAPListen(iface)
+ tap, sink, ready, terminate, err := govpn.TAPListen(iface, peer.Timeout, peer.CPR)
if err != nil {
log.Println("Unable to create Eth", err)
return nil
func main() {
flag.Parse()
- timeout := time.Second * time.Duration(*timeoutP)
+ timeout := time.Second * time.Duration(govpn.TimeoutDefault)
var err error
log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
govpn.MTU = *mtu
- govpn.Timeout = *timeoutP
- govpn.Noncediff = *nonceDiff
govpn.PeersInit(*peersPath)
bind, err := net.ResolveUDPAddr("udp", *bindAddr)
states := make(map[string]*govpn.Handshake)
peers := make(map[string]*PeerState)
peerReadySink := make(chan PeerReadyEvent)
+ knownPeers := govpn.KnownPeers(make(map[string]**govpn.Peer))
var peerReady PeerReadyEvent
- var udpPkt *govpn.UDPPkt
+ var udpPkt govpn.UDPPkt
var udpPktData []byte
var ethEvent EthEvent
+ var peerId *govpn.PeerId
+ var peerConf *govpn.PeerConf
+ var handshakeProcessForce bool
ethSink := make(chan EthEvent)
- log.Println("Server version", govpn.Version)
+ log.Println(govpn.VersionGet())
+ log.Println("Max MTU on TAP interface:", govpn.TAPMaxMTU())
+ if *stats != "" {
+ log.Println("Stats are going to listen on", *stats)
+ statsPort, err := net.Listen("tcp", *stats)
+ if err != nil {
+ panic(err)
+ }
+ go govpn.StatsProcessor(statsPort, &knownPeers)
+ }
log.Println("Server started")
MainCycle:
for addr, hs := range states {
if hs.LastPing.Add(timeout).Before(now) {
log.Println("Deleting handshake state", addr)
+ hs.Zero()
delete(states, addr)
}
}
if state.peer.LastPing.Add(timeout).Before(now) {
log.Println("Deleting peer", state.peer)
delete(peers, addr)
+ delete(knownPeers, addr)
downPath := path.Join(
govpn.PeersPath,
state.peer.Id.String(),
)
go govpn.ScriptCall(downPath, state.tap.Name)
state.terminate <- struct{}{}
+ state.peer.Zero()
}
}
case peerReady = <-peerReadySink:
continue
}
delete(peers, addr)
+ delete(knownPeers, addr)
state.terminate <- struct{}{}
+ state.peer.Zero()
break
}
addr = peerReady.peer.Addr.String()
continue
}
peers[addr] = state
+ knownPeers[addr] = &peerReady.peer
+ states[addr].Zero()
delete(states, addr)
log.Println("Registered interface", peerReady.iface, "with peer", peer)
go func(state *PeerState) {
}
ethEvent.peer.EthProcess(ethEvent.data, conn, ethEvent.ready)
case udpPkt = <-udpSink:
- if udpPkt == nil {
+ if udpPkt.Addr == nil {
udpReady <- struct{}{}
continue
}
udpPktData = udpBuf[:udpPkt.Size]
addr = udpPkt.Addr.String()
- if govpn.IsValidHandshakePkt(udpPktData) {
+ handshakeProcessForce = false
+ HandshakeProcess:
+ if _, exists = peers[addr]; handshakeProcessForce || !exists {
+ peerId = govpn.IDsCache.Find(udpPktData)
+ if peerId == nil {
+ log.Println("Unknown identity from", addr)
+ udpReady <- struct{}{}
+ continue
+ }
+ peerConf = peerId.Conf()
+ if peerConf == nil {
+ log.Println("Can not get peer configuration", peerId.String())
+ udpReady <- struct{}{}
+ continue
+ }
state, exists = states[addr]
if !exists {
- state = govpn.HandshakeNew(udpPkt.Addr)
+ state = govpn.HandshakeNew(udpPkt.Addr, peerConf)
states[addr] = state
}
peer = state.Server(conn, udpPktData)
}()
}
}
- udpReady <- struct{}{}
+ if !handshakeProcessForce {
+ udpReady <- struct{}{}
+ }
continue
}
peerState, exists = peers[addr]
udpReady <- struct{}{}
continue
}
- peerState.peer.UDPProcess(udpPktData, peerState.tap, udpReady)
+ // If it fails during processing, then try to work with it
+ // as with handshake packet
+ if !peerState.peer.UDPProcess(udpPktData, peerState.tap, udpReady) {
+ handshakeProcessForce = true
+ goto HandshakeProcess
+ }
}
}
}