github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/lite2/proxy/proxy.go (about)

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