github.com/vipernet-xyz/tm@v0.34.24/light/proxy/proxy.go (about)

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