func produce_circ() intercom.MultiplexClient {
	xaxa := dirclient.FindExitPath(MasterConfig.Network.MinCircuitLen)
	lel, err := circuitry.BuildCircuit(xaxa, 254)
	if err != nil {
		dirclient.RefreshDirectory()
		time.Sleep(time.Second)
		return produce_circ()
	}
	return intercom.MakeMultiplexClient(lel)
}
func run_client_loop() {
	listener, err := net.Listen("tcp", MasterConfig.General.SocksAddr)
	if err != nil {
		panic(err)
	}
	circ_ch <- produce_circ()
	set_gui_progress(1.0)
	kilog.Info("Bootstrapping 100%%: client started!")

	go func() {
		var haha sync.WaitGroup
		haha.Add(5)
		for i := 0; i < 5; i++ {
			go func() {
				circ_ch <- produce_circ()
				haha.Done()
			}()
		}
		haha.Wait()
	}()
	for {
		nconn, err := listener.Accept()
		if err != nil {
			kilog.Warning("Problem while accepting client socket: %s", err.Error())
			continue
		}
		go func() {
			defer func() {
				nconn.Close()
			}()
			addr, err := socks5.ReadRequest(nconn)
			if err != nil {
				kilog.Warning("Problem while reading SOCKS5 request")
				return
			}
			kilog.Debug("Attempting connection to %s...", addr)
		retry:
			newcirc := <-circ_ch
			remote, err := newcirc.SocksAccept(nconn)
			if err != nil {
				dirclient.RefreshDirectory()
				circ_ch <- produce_circ()
				goto retry
			}
			circ_ch <- newcirc
			defer remote.Close()
			lenbts := []byte{byte((len(addr) + 1) % 256), byte((len(addr) + 1) / 256)}
			_, err = remote.Write(lenbts)
			_, err = remote.Write([]byte(fmt.Sprintf("t%s", addr)))
			if err != nil {
				kilog.Debug("Failed to send tunnelling request to %s!", addr)
				socks5.CompleteRequest(0x03, nconn)
				return
			}

			kilog.Debug("Sent tunneling request")

			code := make([]byte, 4)
			_, err = io.ReadFull(remote, code)
			if err != nil {
				kilog.Debug("Failed to read response for %s! (%s)", addr, err)
				socks5.CompleteRequest(0x03, nconn)
				return
			}

			switch string(code) {
			case "OKAY":
				kilog.Debug("Successfully tunneled %s!", addr)
				socks5.CompleteRequest(0x00, nconn)
				go func() {
					defer remote.Close()
					io.Copy(remote, nconn)
				}()
				io.Copy(nconn, remote)
			case "TMOT":
				kilog.Debug("Tunnel to %s timed out!", addr)
				socks5.CompleteRequest(0x06, nconn)
			case "NOIM":
				kilog.Debug("Tunnel type for %s isn't implemented by server!", addr)
				socks5.CompleteRequest(0x07, nconn)
			case "FAIL":
				kilog.Debug("Tunnel to %s cannot be established!", addr)
				socks5.CompleteRequest(0x04, nconn)
			default:
				kilog.Debug("Protocol error on tunnel to %s! (%s)", addr, string(code))
				socks5.CompleteRequest(0x01, nconn)
				return
			}
		}()
	}
}
func main() {
	rand.Seed(time.Now().UnixNano())
	go run_monitor_loop()
	flag.Parse()
	if *confloc == "" {
		kilog.Warning("No configuration file given, using defaults")
	} else {
		err := gcfg.ReadFileInto(&MasterConfig, *confloc)
		if err != nil {
			kilog.Warning("Configuration file broken, using defaults")
		}
	}
	if *singhop {
		MasterConfig.Network.MinCircuitLen = 1
	}
	kilog.Info("Kirisurf %s started! mkh=%s", version, MasterKeyHash)
	set_gui_progress(0.1)
	kilog.Info("Bootstrapping 10%%: finding directory address...")
	dirclient.DIRADDR, _ = dirclient.FindDirectoryURL()
	set_gui_progress(0.2)
	kilog.Info("Bootstrapping 20%%: found directory address, refreshing directory...")
	err := dirclient.RefreshDirectory()
	if err != nil {
		kilog.Critical("Stuck at 20%%: directory connection error %s", err.Error())
		for {
			time.Sleep(time.Second)
		}
	}
	set_gui_progress(0.3)
	kilog.Info("Bootstrapping 30%%: directory refreshed, beginning to build circuits...")
	go run_diagnostic_loop()
	dirclient.RefreshDirectory()
	if MasterConfig.General.Role == "server" {
		NewSCServer(MasterConfig.General.ORAddr)
		addr := RegisterNGSCServer(MasterConfig.General.ORAddr)
		prt, _ := strconv.Atoi(
			strings.Split(MasterConfig.General.ORAddr, ":")[1])
		go func() {
			err := UPnPForwardAddr(MasterConfig.General.ORAddr)
			err = UPnPForwardAddr(addr)
			if err != nil {
				kilog.Warning("UPnP failed: %s", err)
				if MasterConfig.Network.OverrideUPnP {
					go dirclient.RunRelay(prt, MasterKeyHash,
						MasterConfig.General.IsExit)
				}
				return
			}
			kilog.Info("UPnP successfully forwarded port")
			go dirclient.RunRelay(prt, MasterKeyHash,
				MasterConfig.General.IsExit)
		}()
		kilog.Info("Started server!")
		if *noclient {
			for {
				time.Sleep(time.Second)
			}
		}
	}
	run_client_loop()
	kilog.Info("Kirisurf exited")
}
func sc_server_real_handler(_wire io.ReadWriteCloser) (err error) {
	wire, err := kiss.TransportHandshake(MasterKey, _wire,
		func([]byte) bool { return true })
	if err != nil {
		kilog.Debug("failed the transport handshake")
		return err
	}
	thing := make([]byte, 1)
	_, err = io.ReadFull(wire, thing)
	if err != nil {
		kilog.Debug("failed the readfull")
		return err
	}
	if thing[0] == 0 {
		// Terminate
		if !MasterConfig.General.IsExit {
			return nil
		}
		kilog.Debug("opening legacy (stew) circuit")
		e2e_server_handler_old(wire)
	} else if thing[0] == 255 {
		// Terminate with kinda old
		if !MasterConfig.General.IsExit {
			return nil
		}
		kilog.Debug("opening kinda old circuit")
		e2e_server_kinda_old_handler(wire)
	} else if thing[0] == 254 {
		// Terminate with new
		if !MasterConfig.General.IsExit {
			return nil
		}
		kilog.Debug("opening circuit")
		e2e_server_handler(wire)
	} else {
		xaxa := make([]byte, thing[0])
		_, err := io.ReadFull(wire, xaxa)
		if err != nil {
			return err
		}
		key := string(xaxa)
		qqq := dirclient.PKeyLookup(key)
		if qqq == nil {
			kilog.Debug("Cannot find %s in %v", xaxa, dirclient.KDirectory)
			dirclient.RefreshDirectory()
			qqq = dirclient.PKeyLookup(key)
			if qqq == nil {
				return nil
			}
		}
		kilog.Debug("Continuing to %s", qqq.Address)
		remm, err := circuitry.Dialer.Dial(circuitry.Old2New(qqq.Address))
		if err != nil {
			return err
		}
		go func() {
			io.Copy(wire, remm)
			wire.Close()
		}()
		io.Copy(remm, wire)
		remm.Close()
	}
	return io.EOF
}