Skip to content

Commit b96b497

Browse files
committed
multi: replace standalone gRPC web proxy with unified binary
1 parent e88a9bf commit b96b497

File tree

10 files changed

+1289
-251
lines changed

10 files changed

+1289
-251
lines changed

cmd/shushtar/main.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/jessevdk/go-flags"
8+
"github.com/lightninglabs/shushtar"
9+
)
10+
11+
// main starts the shushtar application.
12+
func main() {
13+
err := shushtar.New().Run()
14+
if e, ok := err.(*flags.Error); err != nil &&
15+
(!ok || e.Type != flags.ErrHelp) {
16+
17+
_, _ = fmt.Fprintln(os.Stderr, err)
18+
os.Exit(1)
19+
}
20+
}

config.go

Lines changed: 171 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,181 @@
1-
package main
1+
package shushtar
22

33
import (
4+
"crypto/tls"
5+
"fmt"
6+
"net"
7+
"os"
8+
"path/filepath"
9+
"strings"
10+
411
"github.com/jessevdk/go-flags"
12+
"github.com/lightninglabs/faraday"
13+
"github.com/lightninglabs/loop/loopd"
14+
"github.com/lightningnetwork/lnd"
15+
"github.com/lightningnetwork/lnd/build"
16+
"github.com/lightningnetwork/lnd/cert"
17+
"github.com/lightningnetwork/lnd/lncfg"
18+
"github.com/mwitkow/go-conntrack/connhelpers"
519
)
620

7-
var (
8-
defaultHTTPSListen = "localhost:8443"
9-
defaultLndHost = "localhost:10009"
10-
defaultLoopHost = "localhost:10010"
11-
defaultTLSCertPath = "https.cert"
12-
defaultTLSKeyPath = "https.key"
13-
)
21+
// Config is the main configuration struct of shushtar. It contains all config
22+
// items of its enveloping subservers, each prefixed with their daemon's short
23+
// name.
24+
type Config struct {
25+
HTTPSListen string `long:"httpslisten" description:"host:port to listen for incoming HTTP/2 connections on"`
26+
Lnd *lnd.Config `group:"lnd" namespace:"lnd"`
27+
Faraday *faraday.Config `group:"faraday" namespace:"faraday"`
28+
Loop *loopd.Config `group:"loop" namespace:"loop"`
29+
}
30+
31+
// loadLndConfig loads and sanitizes the lnd main configuration and hooks up all
32+
// loggers.
33+
func loadLndConfig(preCfg *Config) (*lnd.Config, error) {
34+
// Show the version and exit if the version flag was specified.
35+
appName := filepath.Base(os.Args[0])
36+
appName = strings.TrimSuffix(appName, filepath.Ext(appName))
37+
usageMessage := fmt.Sprintf("Use %s -h to show usage", appName)
38+
if preCfg.Lnd.ShowVersion {
39+
fmt.Println(appName, "version", build.Version(),
40+
"commit="+build.Commit)
41+
os.Exit(0)
42+
}
43+
44+
// If the config file path has not been modified by the user, then we'll
45+
// use the default config file path. However, if the user has modified
46+
// their lnddir, then we should assume they intend to use the config
47+
// file within it.
48+
configFileDir := lnd.CleanAndExpandPath(preCfg.Lnd.LndDir)
49+
configFilePath := lnd.CleanAndExpandPath(preCfg.Lnd.ConfigFile)
50+
if configFileDir != lnd.DefaultLndDir {
51+
if configFilePath == lnd.DefaultConfigFile {
52+
configFilePath = filepath.Join(
53+
configFileDir, lncfg.DefaultConfigFilename,
54+
)
55+
}
56+
}
57+
58+
// Next, load any additional configuration options from the file.
59+
var configFileError error
60+
cfg := preCfg
61+
if err := flags.IniParse(configFilePath, cfg); err != nil {
62+
// If it's a parsing related error, then we'll return
63+
// immediately, otherwise we can proceed as possibly the config
64+
// file doesn't exist which is OK.
65+
if _, ok := err.(*flags.IniError); ok {
66+
return nil, err
67+
}
68+
69+
configFileError = err
70+
}
1471

15-
type config struct {
16-
HTTPSListen string `long:"httpslisten" description:"host:port to listen for incoming HTTP/2 connections on"`
17-
LNDHost string `long:"lndhost" description:"host:port that LND listens for RPC connections on"`
18-
LoopHost string `long:"loophost" description:"host:port that Loop listens for RPC connections on"`
19-
TLSCertPath string `long:"tlscertpath" description:"path to the TLS cert to use for HTTPS requests"`
20-
TLSKeyPath string `long:"tlskeypath" description:"path to the TLS key to use for HTTPS requests"`
21-
}
22-
23-
// loadConfig starts with a skeleton default config, and reads in user provided
24-
// configuration from the command line. It does not provide a full set of
25-
// defaults or validate user input.
26-
func loadConfig() (*config, error) {
27-
// Start with a default config.
28-
config := &config{
29-
HTTPSListen: defaultHTTPSListen,
30-
LNDHost: defaultLndHost,
31-
LoopHost: defaultLoopHost,
32-
TLSCertPath: defaultTLSCertPath,
33-
TLSKeyPath: defaultTLSKeyPath,
34-
}
35-
36-
// Parse command line options to obtain user specified values.
37-
if _, err := flags.Parse(config); err != nil {
72+
// Finally, parse the remaining command line options again to ensure
73+
// they take precedence.
74+
if _, err := flags.Parse(cfg); err != nil {
3875
return nil, err
3976
}
4077

41-
return config, nil
78+
// Make sure everything we just loaded makes sense.
79+
cleanCfg, err := lnd.ValidateConfig(*cfg.Lnd, usageMessage)
80+
if err != nil {
81+
return nil, err
82+
}
83+
84+
// With the validated config obtained, we now know that the root logging
85+
// system of lnd is initialized and we can hook up our own loggers now.
86+
SetupLoggers(cleanCfg.LogWriter)
87+
88+
// Warn about missing config file only after all other configuration is
89+
// done. This prevents the warning on help messages and invalid options.
90+
// Note this should go directly before the return.
91+
if configFileError != nil {
92+
log.Warnf("%v", configFileError)
93+
}
94+
95+
return cleanCfg, nil
96+
}
97+
98+
func getNetwork(cfg *lncfg.Chain) (string, error) {
99+
switch {
100+
case cfg.MainNet:
101+
return "mainnet", nil
102+
103+
case cfg.TestNet3:
104+
return "testnet", nil
105+
106+
case cfg.RegTest:
107+
return "regtest", nil
108+
109+
case cfg.SimNet:
110+
return "simnet", nil
111+
112+
default:
113+
return "", fmt.Errorf("no network selected")
114+
}
115+
}
116+
117+
func buildTLSConfigForHttp2(config *lnd.Config) (*tls.Config, error) {
118+
tlsCert, _, err := cert.LoadCert(config.TLSCertPath, config.TLSKeyPath)
119+
if err != nil {
120+
return nil, fmt.Errorf("failed reading TLS server keys: %v",
121+
err)
122+
}
123+
tlsConfig := cert.TLSConfFromCert(tlsCert)
124+
tlsConfig.CipherSuites = append(
125+
tlsConfig.CipherSuites,
126+
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
127+
)
128+
tlsConfig, err = connhelpers.TlsConfigWithHttp2Enabled(tlsConfig)
129+
if err != nil {
130+
return nil, fmt.Errorf("can't configure h2 handling: %v", err)
131+
}
132+
return tlsConfig, nil
133+
}
134+
135+
// onDemandListener is a net.Listener that only actually starts to listen on a
136+
// network port once the Accept method is called.
137+
type onDemandListener struct {
138+
addr net.Addr
139+
lis net.Listener
140+
}
141+
142+
// Accept waits for and returns the next connection to the listener.
143+
func (l *onDemandListener) Accept() (net.Conn, error) {
144+
if l.lis == nil {
145+
var err error
146+
l.lis, err = net.Listen(parseNetwork(l.addr), l.addr.String())
147+
if err != nil {
148+
return nil, err
149+
}
150+
}
151+
return l.lis.Accept()
152+
}
153+
154+
// Close closes the listener.
155+
// Any blocked Accept operations will be unblocked and return errors.
156+
func (l *onDemandListener) Close() error {
157+
return l.lis.Close()
158+
}
159+
160+
// Addr returns the listener's network address.
161+
func (l *onDemandListener) Addr() net.Addr {
162+
return l.addr
163+
}
164+
165+
// parseNetwork parses the network type of the given address.
166+
func parseNetwork(addr net.Addr) string {
167+
switch addr := addr.(type) {
168+
// TCP addresses resolved through net.ResolveTCPAddr give a default
169+
// network of "tcp", so we'll map back the correct network for the given
170+
// address. This ensures that we can listen on the correct interface
171+
// (IPv4 vs IPv6).
172+
case *net.TCPAddr:
173+
if addr.IP.To4() != nil {
174+
return "tcp4"
175+
}
176+
return "tcp6"
177+
178+
default:
179+
return addr.Network()
180+
}
42181
}

go.mod

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,35 @@
11
module github.com/lightninglabs/shushtar
22

3-
go 1.14
4-
53
require (
4+
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f
65
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
76
github.com/gorilla/websocket v1.4.2 // indirect
8-
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0
9-
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
7+
github.com/grpc-ecosystem/grpc-gateway v1.12.2
108
github.com/improbable-eng/grpc-web v0.12.0
119
github.com/jessevdk/go-flags v1.4.0
12-
github.com/jpillora/backoff v1.0.0 // indirect
10+
github.com/lightninglabs/faraday v0.1.0-alpha.0.20200518080657-d3726a59507c
11+
github.com/lightninglabs/loop v0.6.2-beta.0.20200528104150-c281cab8a036
12+
github.com/lightningnetwork/lnd v0.10.1-beta.rc1
13+
github.com/lightningnetwork/lnd/cert v1.0.2
1314
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
1415
github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76
1516
github.com/prometheus/client_golang v1.5.1 // indirect
17+
github.com/rakyll/statik v0.1.7
1618
github.com/rs/cors v1.7.0 // indirect
17-
github.com/sirupsen/logrus v1.5.0
18-
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
19+
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
1920
golang.org/x/sys v0.0.0-20200406155108-e3b113bbe6a4 // indirect
2021
google.golang.org/grpc v1.28.0
22+
gopkg.in/macaroon-bakery.v2 v2.1.0
23+
gopkg.in/macaroon.v2 v2.1.0
2124
)
25+
26+
// Manually solve the conflict between loop's lndclient version of lnd and what
27+
// we explicitly need for the unified binary to work.
28+
replace github.com/lightningnetwork/lnd => github.com/lightningnetwork/lnd v0.10.0-beta.rc6.0.20200528052558-24c865450a77
29+
30+
// Needed because lnd now imports the etcd client which doesn't follow the go
31+
// mod guidelines. Unfortunately replace directives from dependency projects
32+
// aren't picked up so we need to specify this here and in lnd.
33+
replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.0.0
34+
35+
go 1.13

0 commit comments

Comments
 (0)