You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

104 lines
2.5 KiB

package proxy
import (
"context"
"fmt"
"net"
"net/http"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/log"
tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
lrpc "github.com/tendermint/tendermint/lite2/rpc"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
rpcserver "github.com/tendermint/tendermint/rpc/lib/server"
)
// A Proxy defines parameters for running an HTTP server proxy.
type Proxy struct {
Addr string // TCP address to listen on, ":http" if empty
Config *rpcserver.Config
Codec *amino.Codec
Client *lrpc.Client
Logger log.Logger
Listener net.Listener
}
// ListenAndServe configures the rpcserver.WebsocketManager, sets up the RPC
// routes to proxy via Client, and starts up an HTTP server on the TCP network
// address p.Addr.
// See http#Server#ListenAndServe.
func (p *Proxy) ListenAndServe() error {
listener, mux, err := p.listen()
if err != nil {
return err
}
p.Listener = listener
return rpcserver.StartHTTPServer(
listener,
mux,
p.Logger,
p.Config,
)
}
// ListenAndServeTLS acts identically to ListenAndServe, except that it expects
// HTTPS connections.
// See http#Server#ListenAndServeTLS.
func (p *Proxy) ListenAndServeTLS(certFile, keyFile string) error {
listener, mux, err := p.listen()
if err != nil {
return err
}
p.Listener = listener
return rpcserver.StartHTTPAndTLSServer(
listener,
mux,
certFile,
keyFile,
p.Logger,
p.Config,
)
}
func (p *Proxy) listen() (net.Listener, *http.ServeMux, error) {
ctypes.RegisterAmino(p.Codec)
mux := http.NewServeMux()
// 1) Register regular routes.
r := RPCRoutes(p.Client)
rpcserver.RegisterRPCFuncs(mux, r, p.Codec, p.Logger)
// 2) Allow websocket connections.
wmLogger := p.Logger.With("protocol", "websocket")
wm := rpcserver.NewWebsocketManager(r, p.Codec,
rpcserver.OnDisconnect(func(remoteAddr string) {
err := p.Client.UnsubscribeAll(context.Background(), remoteAddr)
if err != nil && err != tmpubsub.ErrSubscriptionNotFound {
wmLogger.Error("Failed to unsubscribe addr from events", "addr", remoteAddr, "err", err)
}
}),
rpcserver.ReadLimit(p.Config.MaxBodyBytes),
)
wm.SetLogger(wmLogger)
mux.HandleFunc("/websocket", wm.WebsocketHandler)
// 3) Start a client.
if !p.Client.IsRunning() {
if err := p.Client.Start(); err != nil {
return nil, mux, fmt.Errorf("can't start client: %w", err)
}
}
// 4) Start listening for new connections.
listener, err := rpcserver.Listen(p.Addr, p.Config)
if err != nil {
return nil, mux, err
}
return listener, mux, nil
}