func run() error {
	// First, parse configuration file and set up logging.
	configFile := filepath.Join(apertureDataDir, defaultConfigFilename)
	cfg, err := getConfig(configFile)
	if err != nil {
		return fmt.Errorf("unable to parse config file: %v", err)
	}
	err = setupLogging(cfg)
	if err != nil {
		return fmt.Errorf("unable to set up logging: %v", err)
	}

	// Before starting everything, make sure we can intercept any interrupt
	// signals so we can block on waiting for them later.
	err = signal.Intercept()
	if err != nil {
		return err
	}

	// Initialize our etcd client.
	etcdClient, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{cfg.Etcd.Host},
		DialTimeout: 5 * time.Second,
		Username:    cfg.Etcd.User,
		Password:    cfg.Etcd.Password,
	})
	if err != nil {
		return fmt.Errorf("unable to connect to etcd: %v", err)
	}

	// Create our challenger that uses our backing lnd node to create
	// invoices and check their settlement status.
	genInvoiceReq := func(price int64) (*lnrpc.Invoice, error) {
		return &lnrpc.Invoice{
			Memo:  "LSAT",
			Value: price,
		}, nil
	}
	errChan := make(chan error)
	challenger, err := NewLndChallenger(
		cfg.Authenticator, genInvoiceReq, errChan,
	)
	if err != nil {
		return err
	}
	err = challenger.Start()
	if err != nil {
		return err
	}
	defer challenger.Stop()

	// Create the proxy and connect it to lnd.
	servicesProxy, err := createProxy(cfg, challenger, etcdClient)
	if err != nil {
		return err
	}
	handler := http.HandlerFunc(servicesProxy.ServeHTTP)
	httpsServer := &http.Server{
		Addr:    cfg.ListenAddr,
		Handler: handler,
	}

	// Create TLS configuration by either creating new self-signed certs or
	// trying to obtain one through Let's Encrypt.
	var serveFn func() error
	if cfg.Insecure {
		// Normally, HTTP/2 only works with TLS. But there is a special
		// version called HTTP/2 Cleartext (h2c) that some clients
		// support and that gRPC uses when the grpc.WithInsecure()
		// option is used. The default HTTP handler doesn't support it
		// though so we need to add a special h2c handler here.
		serveFn = httpsServer.ListenAndServe
		httpsServer.Handler = h2c.NewHandler(handler, &http2.Server{})
	} else {
		httpsServer.TLSConfig, err = getTLSConfig(
			cfg.ServerName, cfg.AutoCert,
		)
		if err != nil {
			return err
		}
		serveFn = func() error {
			// The httpsServer.TLSConfig contains certificates at
			// this point so we don't need to pass in certificate
			// and key file names.
			return httpsServer.ListenAndServeTLS("", "")
		}
	}

	// Finally run the server.
	var (
		wg   sync.WaitGroup
		quit = make(chan struct{})
	)
	log.Infof("Starting the server, listening on %s.", cfg.ListenAddr)

	wg.Add(1)
	go func() {
		defer wg.Done()

		select {
		case errChan <- serveFn():
		case <-quit:
		}
	}()

	// If we need to listen over Tor as well, we'll set up the onion
	// services now. We're not able to use TLS for onion services since they
	// can't be verified, so we'll spin up an additional HTTP/2 server
	// _without_ TLS that is not exposed to the outside world. This server
	// will only be reached through the onion services, which already
	// provide encryption, so running this additional HTTP server should be
	// relatively safe.
	var torHTTPServer *http.Server
	if cfg.Tor != nil && (cfg.Tor.V2 || cfg.Tor.V3) {
		torController, err := initTorListener(cfg, etcdClient)
		if err != nil {
			return err
		}
		defer func() {
			_ = torController.Stop()
		}()

		torHTTPServer = &http.Server{
			Addr:    fmt.Sprintf("localhost:%d", cfg.Tor.ListenPort),
			Handler: h2c.NewHandler(handler, &http2.Server{}),
		}
		wg.Add(1)
		go func() {
			defer wg.Done()

			select {
			case errChan <- torHTTPServer.ListenAndServe():
			case <-quit:
			}
		}()
	}

	var returnErr error
	select {
	case <-signal.ShutdownChannel():
		log.Infof("Received interrupt signal, shutting down aperture.")

	case err := <-errChan:
		log.Errorf("Error while running aperture: %v", err)
		returnErr = err
	}

	// Shut down our client and server connections now. This should cause
	// the first goroutine to quit.
	cleanup(etcdClient, httpsServer)

	// If we started a tor server as well, shut it down now too to cause the
	// second goroutine to quit.
	if torHTTPServer != nil {
		_ = torHTTPServer.Close()
	}

	// Now we wait for the goroutines to exit before we return. The defers
	// will take care of the rest of our started resources.
	close(quit)
	wg.Wait()

	return returnErr
}
// run sets up the proxy server and runs it. This function blocks until a
// shutdown signal is received.
run sets up the proxy server and runs it. This function blocks until a
shutdown signal is received.
// run sets up the proxy server and runs it . This function blocks until a // shutdown signal is received .
func run() error {
	configFile := filepath.Join(apertureDataDir, defaultConfigFilename)
	cfg, err := getConfig(configFile)
	if err != nil {
		return fmt.Errorf("unable to parse config file: %v", err)
	}
	err = setupLogging(cfg)
	if err != nil {
		return fmt.Errorf("unable to set up logging: %v", err)
	}
	err = signal.Intercept()
	if err != nil {
		return err
	}
	etcdClient, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{cfg.Etcd.Host},
		DialTimeout: 5 * time.Second,
		Username:    cfg.Etcd.User,
		Password:    cfg.Etcd.Password,
	})
	if err != nil {
		return fmt.Errorf("unable to connect to etcd: %v", err)
	}
	genInvoiceReq := func(price int64) (*lnrpc.Invoice, error) {
		return &lnrpc.Invoice{
			Memo:  "LSAT",
			Value: price,
		}, nil
	}
	errChan := make(chan error)
	challenger, err := NewLndChallenger(
		cfg.Authenticator, genInvoiceReq, errChan,
	)
	if err != nil {
		return err
	}
	err = challenger.Start()
	if err != nil {
		return err
	}
	defer challenger.Stop()
	servicesProxy, err := createProxy(cfg, challenger, etcdClient)
	if err != nil {
		return err
	}
	handler := http.HandlerFunc(servicesProxy.ServeHTTP)
	httpsServer := &http.Server{
		Addr:    cfg.ListenAddr,
		Handler: handler,
	}
	var serveFn func() error
	if cfg.Insecure {
		serveFn = httpsServer.ListenAndServe
		httpsServer.Handler = h2c.NewHandler(handler, &http2.Server{})
	} else {
		httpsServer.TLSConfig, err = getTLSConfig(
			cfg.ServerName, cfg.AutoCert,
		)
		if err != nil {
			return err
		}
		serveFn = func() error {
			return httpsServer.ListenAndServeTLS("", "")
		}
	}
	var (
		wg   sync.WaitGroup
		quit = make(chan struct{})
	)
	log.Infof("Starting the server, listening on %s.", cfg.ListenAddr)
	wg.Add(1)
	go func() {
		defer wg.Done()
		select {
		case errChan <- serveFn():
		case <-quit:
		}
	}()
	var torHTTPServer *http.Server
	if cfg.Tor != nil && (cfg.Tor.V2 || cfg.Tor.V3) {
		torController, err := initTorListener(cfg, etcdClient)
		if err != nil {
			return err
		}
		defer func() {
			_ = torController.Stop()
		}()
		torHTTPServer = &http.Server{
			Addr:    fmt.Sprintf("localhost:%d", cfg.Tor.ListenPort),
			Handler: h2c.NewHandler(handler, &http2.Server{}),
		}
		wg.Add(1)
		go func() {
			defer wg.Done()
			select {
			case errChan <- torHTTPServer.ListenAndServe():
			case <-quit:
			}
		}()
	}
	var returnErr error
	select {
	case <-signal.ShutdownChannel():
		log.Infof("Received interrupt signal, shutting down aperture.")
	case err := <-errChan:
		log.Errorf("Error while running aperture: %v", err)
		returnErr = err
	}
	cleanup(etcdClient, httpsServer)
	if torHTTPServer != nil {
		_ = torHTTPServer.Close()
	}
	close(quit)
	wg.Wait()
	return returnErr
}
func run ( ) error { configFile := filepath . Join ( apertureDataDir , defaultConfigFilename ) cfg , err := getConfig ( configFile ) if err != nil { return fmt . Errorf ( " " , err ) } err = setupLogging ( cfg ) if err != nil { return fmt . Errorf ( " " , err ) } err = signal . Intercept ( ) if err != nil { return err } etcdClient , err := clientv3 . New ( clientv3 . Config { Endpoints : [ ] string { cfg . Etcd . Host } , DialTimeout : 5 * time . Second , Username : cfg . Etcd . User , Password : cfg . Etcd . Password , } ) if err != nil { return fmt . Errorf ( " " , err ) } genInvoiceReq := func ( price int64 ) ( * lnrpc . Invoice , error ) { return & lnrpc . Invoice { Memo : " " , Value : price , } , nil } errChan := make ( chan error ) challenger , err := NewLndChallenger ( cfg . Authenticator , genInvoiceReq , errChan , ) if err != nil { return err } err = challenger . Start ( ) if err != nil { return err } defer challenger . Stop ( ) servicesProxy , err := createProxy ( cfg , challenger , etcdClient ) if err != nil { return err } handler := http . HandlerFunc ( servicesProxy . ServeHTTP ) httpsServer := & http . Server { Addr : cfg . ListenAddr , Handler : handler , } var serveFn func ( ) error if cfg . Insecure { serveFn = httpsServer . ListenAndServe httpsServer . Handler = h2c . NewHandler ( handler , & http2 . Server { } ) } else { httpsServer . TLSConfig , err = getTLSConfig ( cfg . ServerName , cfg . AutoCert , ) if err != nil { return err } serveFn = func ( ) error { return httpsServer . ListenAndServeTLS ( " " , " " ) } } var ( wg sync . WaitGroup quit = make ( chan struct { } ) ) log . Infof ( " " , cfg . ListenAddr ) wg . Add ( 1 ) go func ( ) { defer wg . Done ( ) select { case errChan <- serveFn ( ) : case <- quit : } } ( ) var torHTTPServer * http . Server if cfg . Tor != nil && ( cfg . Tor . V2 || cfg . Tor . V3 ) { torController , err := initTorListener ( cfg , etcdClient ) if err != nil { return err } defer func ( ) { _ = torController . Stop ( ) } ( ) torHTTPServer = & http . Server { Addr : fmt . Sprintf ( " " , cfg . Tor . ListenPort ) , Handler : h2c . NewHandler ( handler , & http2 . Server { } ) , } wg . Add ( 1 ) go func ( ) { defer wg . Done ( ) select { case errChan <- torHTTPServer . ListenAndServe ( ) : case <- quit : } } ( ) } var returnErr error select { case <- signal . ShutdownChannel ( ) : log . Infof ( " " ) case err := <- errChan : log . Errorf ( " " , err ) returnErr = err } cleanup ( etcdClient , httpsServer ) if torHTTPServer != nil { _ = torHTTPServer . Close ( ) } close ( quit ) wg . Wait ( ) return returnErr }
run sets up the proxy server and runs it.
run sets up the proxy server and runs it .
// First, parse configuration file and set up logging. // Before starting everything, make sure we can intercept any interrupt // signals so we can block on waiting for them later. // Initialize our etcd client. // Create our challenger that uses our backing lnd node to create // invoices and check their settlement status. // Create the proxy and connect it to lnd. // Create TLS configuration by either creating new self-signed certs or // trying to obtain one through Let's Encrypt. // Normally, HTTP/2 only works with TLS. But there is a special // version called HTTP/2 Cleartext (h2c) that some clients // support and that gRPC uses when the grpc.WithInsecure() // option is used. The default HTTP handler doesn't support it // though so we need to add a special h2c handler here. // The httpsServer.TLSConfig contains certificates at // this point so we don't need to pass in certificate // and key file names. // Finally run the server. // If we need to listen over Tor as well, we'll set up the onion // services now. We're not able to use TLS for onion services since they // can't be verified, so we'll spin up an additional HTTP/2 server // _without_ TLS that is not exposed to the outside world. This server // will only be reached through the onion services, which already // provide encryption, so running this additional HTTP server should be // relatively safe. // Shut down our client and server connections now. This should cause // the first goroutine to quit. // If we started a tor server as well, shut it down now too to cause the // second goroutine to quit. // Now we wait for the goroutines to exit before we return. The defers // will take care of the rest of our started resources.