github.com/516108736/tendermint@v0.36.0/light/proxy/proxy.go (about)

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