func ServerStart(bindAddr, proto, confPath, stats, proxy, egdPath string, mtu int) { timeout := time.Second * time.Duration(govpn.TimeoutDefault) log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile) log.Println(govpn.VersionGet()) if len(bindAddr) <= 0 { bindAddr = "[::]:1194" } if len(proto) <= 0 { proto = "udp" } if len(confPath) <= 0 { confPath = "peers.json" } if mtu <= 0 { mtu = 1452 } govpn.MTU = mtu confInit(&confPath) knownPeers = govpn.KnownPeers(make(map[string]**govpn.Peer)) if egdPath != "" { log.Println("Using", egdPath, "EGD") govpn.EGDInit(egdPath) } switch proto { case "udp": startUDP(&bindAddr) case "tcp": startTCP(&bindAddr) case "all": startUDP(&bindAddr) startTCP(&bindAddr) default: log.Fatalln("Unknown protocol specified") } termSignal := make(chan os.Signal, 1) signal.Notify(termSignal, os.Interrupt, os.Kill) hsHeartbeat := time.Tick(timeout) go func() { <-hsHeartbeat }() 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 { log.Fatalln("Can not listen on stats port:", err) } go govpn.StatsProcessor(statsPort, &knownPeers) } if proxy != "" { go proxyStart(&proxy) } log.Println("Server started") var needsDeletion bool MainCycle: for { select { case <-termSignal: break MainCycle case <-hsHeartbeat: now := time.Now() hsLock.Lock() for addr, hs := range handshakes { if hs.LastPing.Add(timeout).Before(now) { log.Println("Deleting handshake state", addr) hs.Zero() delete(handshakes, addr) } } peersLock.Lock() peersByIdLock.Lock() kpLock.Lock() for addr, ps := range peers { ps.peer.BusyR.Lock() needsDeletion = ps.peer.LastPing.Add(timeout).Before(now) ps.peer.BusyR.Unlock() if needsDeletion { log.Println("Deleting peer", ps.peer) delete(peers, addr) delete(knownPeers, addr) delete(peersById, *ps.peer.Id) go govpn.ScriptCall( confs[*ps.peer.Id].Down, ps.tap.Name, ) ps.terminator <- struct{}{} } } hsLock.Unlock() peersLock.Unlock() peersByIdLock.Unlock() kpLock.Unlock() } } }
func main() { flag.Parse() timeout = *timeoutP var err error log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile) govpn.MTU = *mtu if *egdPath != "" { log.Println("Using", *egdPath, "EGD") govpn.EGDInit(*egdPath) } verifier, err := govpn.VerifierFromString(*verifierRaw) if err != nil { log.Fatalln(err) } priv := verifier.PasswordApply(govpn.StringFromFile(*keyPath)) conf = &govpn.PeerConf{ Id: verifier.Id, Timeout: time.Second * time.Duration(timeout), Noise: *noisy, CPR: *cpr, Verifier: verifier, DSAPriv: priv, } idsCache = govpn.NewCipherCache([]govpn.PeerId{*verifier.Id}) log.Println(govpn.VersionGet()) tap, err = govpn.TAPListen(*ifaceName) if err != nil { log.Fatalln("Can not listen on TAP interface:", err) } 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 { log.Fatalln("Can not listen on stats port:", err) } go govpn.StatsProcessor(statsPort, &knownPeers) } termSignal := make(chan os.Signal, 1) signal.Notify(termSignal, os.Interrupt, os.Kill) MainCycle: for { timeouted := make(chan struct{}) rehandshaking := make(chan struct{}) termination := make(chan struct{}) if *proxyAddr != "" { *proto = "tcp" } switch *proto { case "udp": go startUDP(timeouted, rehandshaking, termination) case "tcp": if *proxyAddr != "" { go proxyTCP(timeouted, rehandshaking, termination) } else { go startTCP(timeouted, rehandshaking, termination) } default: log.Fatalln("Unknown protocol specified") } select { case <-termSignal: log.Fatalln("Finishing") termination <- struct{}{} break MainCycle case <-timeouted: break MainCycle case <-rehandshaking: } close(timeouted) close(rehandshaking) close(termination) } govpn.ScriptCall(*downPath, *ifaceName) }