github.com/vipernet-xyz/tendermint-core@v0.32.0/lite2/proxy/proxy.go (about)

     1  package proxy
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"net/http"
     7  
     8  	"github.com/pkg/errors"
     9  
    10  	amino "github.com/tendermint/go-amino"
    11  
    12  	"github.com/tendermint/tendermint/libs/log"
    13  	tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
    14  	lrpc "github.com/tendermint/tendermint/lite2/rpc"
    15  	ctypes "github.com/tendermint/tendermint/rpc/core/types"
    16  	rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
    17  )
    18  
    19  // A Proxy defines parameters for running an HTTP server proxy.
    20  type Proxy struct {
    21  	Addr     string // TCP address to listen on, ":http" if empty
    22  	Config   *rpcserver.Config
    23  	Codec    *amino.Codec
    24  	Client   *lrpc.Client
    25  	Logger   log.Logger
    26  	Listener net.Listener
    27  }
    28  
    29  // ListenAndServe configures the rpcserver.WebsocketManager, sets up the RPC
    30  // routes to proxy via Client, and starts up an HTTP server on the TCP network
    31  // address p.Addr.
    32  // See http#Server#ListenAndServe.
    33  func (p *Proxy) ListenAndServe() error {
    34  	listener, mux, err := p.listen()
    35  	if err != nil {
    36  		return err
    37  	}
    38  	p.Listener = listener
    39  
    40  	return rpcserver.Serve(
    41  		listener,
    42  		mux,
    43  		p.Logger,
    44  		p.Config,
    45  	)
    46  }
    47  
    48  // ListenAndServeTLS acts identically to ListenAndServe, except that it expects
    49  // HTTPS connections.
    50  // See http#Server#ListenAndServeTLS.
    51  func (p *Proxy) ListenAndServeTLS(certFile, keyFile string) error {
    52  	listener, mux, err := p.listen()
    53  	if err != nil {
    54  		return err
    55  	}
    56  	p.Listener = listener
    57  
    58  	return rpcserver.ServeTLS(
    59  		listener,
    60  		mux,
    61  		certFile,
    62  		keyFile,
    63  		p.Logger,
    64  		p.Config,
    65  	)
    66  }
    67  
    68  func (p *Proxy) listen() (net.Listener, *http.ServeMux, error) {
    69  	ctypes.RegisterAmino(p.Codec)
    70  
    71  	mux := http.NewServeMux()
    72  
    73  	// 1) Register regular routes.
    74  	r := RPCRoutes(p.Client)
    75  	rpcserver.RegisterRPCFuncs(mux, r, p.Codec, p.Logger)
    76  
    77  	// 2) Allow websocket connections.
    78  	wmLogger := p.Logger.With("protocol", "websocket")
    79  	wm := rpcserver.NewWebsocketManager(r, p.Codec,
    80  		rpcserver.OnDisconnect(func(remoteAddr string) {
    81  			err := p.Client.UnsubscribeAll(context.Background(), remoteAddr)
    82  			if err != nil && err != tmpubsub.ErrSubscriptionNotFound {
    83  				wmLogger.Error("Failed to unsubscribe addr from events", "addr", remoteAddr, "err", err)
    84  			}
    85  		}),
    86  		rpcserver.ReadLimit(p.Config.MaxBodyBytes),
    87  	)
    88  	wm.SetLogger(wmLogger)
    89  	mux.HandleFunc("/websocket", wm.WebsocketHandler)
    90  
    91  	// 3) Start a client.
    92  	if !p.Client.IsRunning() {
    93  		if err := p.Client.Start(); err != nil {
    94  			return nil, mux, errors.Wrap(err, "Client#Start")
    95  		}
    96  	}
    97  
    98  	// 4) Start listening for new connections.
    99  	listener, err := rpcserver.Listen(p.Addr, p.Config)
   100  	if err != nil {
   101  		return nil, mux, err
   102  	}
   103  
   104  	return listener, mux, nil
   105  }