github.com/okex/exchain@v1.8.0/libs/tendermint/rpc/client/http/http.go (about)

     1  package http
     2  
     3  import (
     4  	"context"
     5  	"crypto/sha256"
     6  	"net/http"
     7  	"strings"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/pkg/errors"
    12  
    13  	amino "github.com/tendermint/go-amino"
    14  
    15  	"github.com/okex/exchain/libs/tendermint/libs/bytes"
    16  	"github.com/okex/exchain/libs/tendermint/libs/log"
    17  	tmpubsub "github.com/okex/exchain/libs/tendermint/libs/pubsub"
    18  	"github.com/okex/exchain/libs/tendermint/libs/service"
    19  	rpcclient "github.com/okex/exchain/libs/tendermint/rpc/client"
    20  	ctypes "github.com/okex/exchain/libs/tendermint/rpc/core/types"
    21  	jsonrpcclient "github.com/okex/exchain/libs/tendermint/rpc/jsonrpc/client"
    22  	"github.com/okex/exchain/libs/tendermint/types"
    23  )
    24  
    25  /*
    26  HTTP is a Client implementation that communicates with a Tendermint node over
    27  JSON RPC and WebSockets.
    28  
    29  This is the main implementation you probably want to use in production code.
    30  There are other implementations when calling the Tendermint node in-process
    31  (Local), or when you want to mock out the server for test code (mock).
    32  
    33  You can subscribe for any event published by Tendermint using Subscribe method.
    34  Note delivery is best-effort. If you don't read events fast enough or network is
    35  slow, Tendermint might cancel the subscription. The client will attempt to
    36  resubscribe (you don't need to do anything). It will keep trying every second
    37  indefinitely until successful.
    38  
    39  Request batching is available for JSON RPC requests over HTTP, which conforms to
    40  the JSON RPC specification (https://www.jsonrpc.org/specification#batch). See
    41  the example for more details.
    42  
    43  Example:
    44  
    45  		c, err := New("http://192.168.1.10:26657", "/websocket")
    46  		if err != nil {
    47  			// handle error
    48  		}
    49  
    50  		// call Start/Stop if you're subscribing to events
    51  		err = c.Start()
    52  		if err != nil {
    53  			// handle error
    54  		}
    55  		defer c.Stop()
    56  
    57  		res, err := c.Status()
    58  		if err != nil {
    59  			// handle error
    60  		}
    61  
    62  		// handle result
    63  */
    64  type HTTP struct {
    65  	remote string
    66  	rpc    *jsonrpcclient.Cm39HttpJSONClientAdapter
    67  
    68  	*baseRPCClient
    69  	*WSEvents
    70  }
    71  
    72  func (c *HTTP) GetUnconfirmedTxByHash(hash [sha256.Size]byte) (types.Tx, error) {
    73  	return nil, errors.New("unhandled method")
    74  }
    75  
    76  // BatchHTTP provides the same interface as `HTTP`, but allows for batching of
    77  // requests (as per https://www.jsonrpc.org/specification#batch). Do not
    78  // instantiate directly - rather use the HTTP.NewBatch() method to create an
    79  // instance of this struct.
    80  //
    81  // Batching of HTTP requests is thread-safe in the sense that multiple
    82  // goroutines can each create their own batches and send them using the same
    83  // HTTP client. Multiple goroutines could also enqueue transactions in a single
    84  // batch, but ordering of transactions in the batch cannot be guaranteed in such
    85  // an example.
    86  type BatchHTTP struct {
    87  	rpcBatch *jsonrpcclient.RequestBatch
    88  	*baseRPCClient
    89  }
    90  
    91  // rpcClient is an internal interface to which our RPC clients (batch and
    92  // non-batch) must conform. Acts as an additional code-level sanity check to
    93  // make sure the implementations stay coherent.
    94  type rpcClient interface {
    95  	rpcclient.ABCIClient
    96  	rpcclient.HistoryClient
    97  	rpcclient.NetworkClient
    98  	rpcclient.SignClient
    99  	rpcclient.StatusClient
   100  }
   101  
   102  // baseRPCClient implements the basic RPC method logic without the actual
   103  // underlying RPC call functionality, which is provided by `caller`.
   104  type baseRPCClient struct {
   105  	caller jsonrpcclient.Caller
   106  }
   107  
   108  var _ rpcClient = (*HTTP)(nil)
   109  var _ rpcClient = (*BatchHTTP)(nil)
   110  var _ rpcClient = (*baseRPCClient)(nil)
   111  
   112  //-----------------------------------------------------------------------------
   113  // HTTP
   114  
   115  // New takes a remote endpoint in the form <protocol>://<host>:<port> and
   116  // the websocket path (which always seems to be "/websocket")
   117  // An error is returned on invalid remote. The function panics when remote is nil.
   118  func New(remote, wsEndpoint string) (*HTTP, error) {
   119  	httpClient, err := jsonrpcclient.DefaultHTTPClient(remote)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	return NewWithClient(remote, wsEndpoint, httpClient)
   124  }
   125  
   126  // Create timeout enabled http client
   127  func NewWithTimeout(remote, wsEndpoint string, timeout uint) (*HTTP, error) {
   128  	httpClient, err := jsonrpcclient.DefaultHTTPClient(remote)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  	httpClient.Timeout = time.Duration(timeout) * time.Second
   133  	return NewWithClient(remote, wsEndpoint, httpClient)
   134  }
   135  
   136  // NewWithClient allows for setting a custom http client (See New).
   137  // An error is returned on invalid remote. The function panics when remote is nil.
   138  func NewWithClient(remote, wsEndpoint string, client *http.Client) (*HTTP, error) {
   139  	if client == nil {
   140  		panic("nil http.Client provided")
   141  	}
   142  
   143  	rc, err := jsonrpcclient.NewCm39HttpJSONClient(remote, client)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  	cdc := rc.Codec()
   148  	ctypes.RegisterAmino(cdc)
   149  	rc.SetCodec(cdc)
   150  
   151  	wsEvents, err := newWSEvents(cdc, remote, wsEndpoint)
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  
   156  	httpClient := &HTTP{
   157  		rpc:           rc,
   158  		remote:        remote,
   159  		baseRPCClient: &baseRPCClient{caller: rc},
   160  		WSEvents:      wsEvents,
   161  	}
   162  
   163  	return httpClient, nil
   164  }
   165  
   166  var _ rpcclient.Client = (*HTTP)(nil)
   167  
   168  // SetLogger sets a logger.
   169  func (c *HTTP) SetLogger(l log.Logger) {
   170  	c.WSEvents.SetLogger(l)
   171  }
   172  
   173  // Remote returns the remote network address in a string form.
   174  func (c *HTTP) Remote() string {
   175  	return c.remote
   176  }
   177  
   178  // NewBatch creates a new batch client for this HTTP client.
   179  func (c *HTTP) NewBatch() *BatchHTTP {
   180  	rpcBatch := c.rpc.NewRequestBatch()
   181  	return &BatchHTTP{
   182  		rpcBatch: rpcBatch,
   183  		baseRPCClient: &baseRPCClient{
   184  			caller: rpcBatch,
   185  		},
   186  	}
   187  }
   188  
   189  //-----------------------------------------------------------------------------
   190  // BatchHTTP
   191  
   192  // Send is a convenience function for an HTTP batch that will trigger the
   193  // compilation of the batched requests and send them off using the client as a
   194  // single request. On success, this returns a list of the deserialized results
   195  // from each request in the sent batch.
   196  func (b *BatchHTTP) Send() ([]interface{}, error) {
   197  	return b.rpcBatch.Send()
   198  }
   199  
   200  // Clear will empty out this batch of requests and return the number of requests
   201  // that were cleared out.
   202  func (b *BatchHTTP) Clear() int {
   203  	return b.rpcBatch.Clear()
   204  }
   205  
   206  // Count returns the number of enqueued requests waiting to be sent.
   207  func (b *BatchHTTP) Count() int {
   208  	return b.rpcBatch.Count()
   209  }
   210  
   211  //-----------------------------------------------------------------------------
   212  // baseRPCClient
   213  
   214  func (c *baseRPCClient) Status() (*ctypes.ResultStatus, error) {
   215  	result := new(ctypes.ResultStatus)
   216  	_, err := c.caller.Call("status", map[string]interface{}{}, result)
   217  	if err != nil {
   218  		return nil, errors.Wrap(err, "Status")
   219  	}
   220  	return result, nil
   221  }
   222  
   223  func (c *baseRPCClient) ABCIInfo() (*ctypes.ResultABCIInfo, error) {
   224  	result := new(ctypes.ResultABCIInfo)
   225  	_, err := c.caller.Call("abci_info", map[string]interface{}{}, result)
   226  	if err != nil {
   227  		return nil, errors.Wrap(err, "ABCIInfo")
   228  	}
   229  	return result, nil
   230  }
   231  
   232  func (c *baseRPCClient) ABCIQuery(path string, data bytes.HexBytes) (*ctypes.ResultABCIQuery, error) {
   233  	return c.ABCIQueryWithOptions(path, data, rpcclient.DefaultABCIQueryOptions)
   234  }
   235  
   236  func (c *baseRPCClient) ABCIQueryWithOptions(
   237  	path string,
   238  	data bytes.HexBytes,
   239  	opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
   240  	result := new(ctypes.ResultABCIQuery)
   241  	_, err := c.caller.Call("abci_query",
   242  		map[string]interface{}{"path": path, "data": data, "height": opts.Height, "prove": opts.Prove},
   243  		result)
   244  	if err != nil {
   245  		return nil, errors.Wrap(err, "ABCIQuery")
   246  	}
   247  	return result, nil
   248  }
   249  
   250  func (c *baseRPCClient) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
   251  	result := new(ctypes.ResultBroadcastTxCommit)
   252  	_, err := c.caller.Call("broadcast_tx_commit", map[string]interface{}{"tx": tx}, result)
   253  	if err != nil {
   254  		return nil, errors.Wrap(err, "broadcast_tx_commit")
   255  	}
   256  	return result, nil
   257  }
   258  
   259  func (c *baseRPCClient) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   260  	return c.broadcastTX("broadcast_tx_async", tx)
   261  }
   262  
   263  func (c *baseRPCClient) BroadcastTxSync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   264  	return c.broadcastTX("broadcast_tx_sync", tx)
   265  }
   266  
   267  func (c *baseRPCClient) broadcastTX(route string, tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   268  	result := new(ctypes.ResultBroadcastTx)
   269  	_, err := c.caller.Call(route, map[string]interface{}{"tx": tx}, result)
   270  	if err != nil {
   271  		return nil, errors.Wrap(err, route)
   272  	}
   273  	return result, nil
   274  }
   275  
   276  func (c *baseRPCClient) UnconfirmedTxs(limit int) (*ctypes.ResultUnconfirmedTxs, error) {
   277  	result := new(ctypes.ResultUnconfirmedTxs)
   278  	_, err := c.caller.Call("unconfirmed_txs", map[string]interface{}{"limit": limit}, result)
   279  	if err != nil {
   280  		return nil, errors.Wrap(err, "unconfirmed_txs")
   281  	}
   282  	return result, nil
   283  }
   284  
   285  func (c *baseRPCClient) NumUnconfirmedTxs() (*ctypes.ResultUnconfirmedTxs, error) {
   286  	result := new(ctypes.ResultUnconfirmedTxs)
   287  	_, err := c.caller.Call("num_unconfirmed_txs", map[string]interface{}{}, result)
   288  	if err != nil {
   289  		return nil, errors.Wrap(err, "num_unconfirmed_txs")
   290  	}
   291  	return result, nil
   292  }
   293  
   294  func (c *baseRPCClient) UserUnconfirmedTxs(address string, limit int) (*ctypes.ResultUserUnconfirmedTxs, error) {
   295  	result := new(ctypes.ResultUserUnconfirmedTxs)
   296  	_, err := c.caller.Call("user_unconfirmed_txs", map[string]interface{}{"address": address, "limit": limit}, result)
   297  	if err != nil {
   298  		return nil, errors.Wrap(err, "user_unconfirmed_txs")
   299  	}
   300  	return result, nil
   301  }
   302  
   303  func (c *baseRPCClient) UserNumUnconfirmedTxs(address string) (*ctypes.ResultUserUnconfirmedTxs, error) {
   304  	result := new(ctypes.ResultUserUnconfirmedTxs)
   305  	_, err := c.caller.Call("user_num_unconfirmed_txs", map[string]interface{}{"address": address}, result)
   306  	if err != nil {
   307  		return nil, errors.Wrap(err, "user_num_unconfirmed_txs")
   308  	}
   309  	return result, nil
   310  }
   311  
   312  func (c *baseRPCClient) GetAddressList() (*ctypes.ResultUnconfirmedAddresses, error) {
   313  	result := new(ctypes.ResultUnconfirmedAddresses)
   314  	_, err := c.caller.Call("get_address_list", map[string]interface{}{}, result)
   315  	if err != nil {
   316  		return nil, errors.Wrap(err, "get_address_list")
   317  	}
   318  	return result, nil
   319  }
   320  
   321  func (c *baseRPCClient) GetPendingNonce(address string) (*ctypes.ResultPendingNonce, bool) {
   322  	result := new(ctypes.ResultPendingNonce)
   323  	_, err := c.caller.Call("get_pending_nonce", map[string]interface{}{"address": address}, result)
   324  	if err != nil {
   325  		return nil, false
   326  	}
   327  	return result, true
   328  }
   329  
   330  func (c *baseRPCClient) NetInfo() (*ctypes.ResultNetInfo, error) {
   331  	result := new(ctypes.ResultNetInfo)
   332  	_, err := c.caller.Call("net_info", map[string]interface{}{}, result)
   333  	if err != nil {
   334  		return nil, errors.Wrap(err, "NetInfo")
   335  	}
   336  	return result, nil
   337  }
   338  
   339  func (c *baseRPCClient) DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
   340  	result := new(ctypes.ResultDumpConsensusState)
   341  	_, err := c.caller.Call("dump_consensus_state", map[string]interface{}{}, result)
   342  	if err != nil {
   343  		return nil, errors.Wrap(err, "DumpConsensusState")
   344  	}
   345  	return result, nil
   346  }
   347  
   348  func (c *baseRPCClient) ConsensusState() (*ctypes.ResultConsensusState, error) {
   349  	result := new(ctypes.ResultConsensusState)
   350  	_, err := c.caller.Call("consensus_state", map[string]interface{}{}, result)
   351  	if err != nil {
   352  		return nil, errors.Wrap(err, "ConsensusState")
   353  	}
   354  	return result, nil
   355  }
   356  
   357  func (c *baseRPCClient) ConsensusParams(height *int64) (*ctypes.ResultConsensusParams, error) {
   358  	result := new(ctypes.ResultConsensusParams)
   359  	_, err := c.caller.Call("consensus_params", map[string]interface{}{"height": height}, result)
   360  	if err != nil {
   361  		return nil, errors.Wrap(err, "ConsensusParams")
   362  	}
   363  	return result, nil
   364  }
   365  
   366  func (c *baseRPCClient) Health() (*ctypes.ResultHealth, error) {
   367  	result := new(ctypes.ResultHealth)
   368  	_, err := c.caller.Call("health", map[string]interface{}{}, result)
   369  	if err != nil {
   370  		return nil, errors.Wrap(err, "Health")
   371  	}
   372  	return result, nil
   373  }
   374  
   375  func (c *baseRPCClient) BlockchainInfo(minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) {
   376  	result := new(ctypes.ResultBlockchainInfo)
   377  	_, err := c.caller.Call("blockchain",
   378  		map[string]interface{}{"minHeight": minHeight, "maxHeight": maxHeight},
   379  		result)
   380  	if err != nil {
   381  		return nil, errors.Wrap(err, "BlockchainInfo")
   382  	}
   383  	return result, nil
   384  }
   385  
   386  func (c *baseRPCClient) LatestBlockNumber() (int64, error) {
   387  	info, err := c.BlockchainInfo(0, 0)
   388  	if err != nil {
   389  		return 0, err
   390  	}
   391  	return info.LastHeight, nil
   392  }
   393  
   394  func (c *baseRPCClient) Genesis() (*ctypes.ResultGenesis, error) {
   395  	result := new(ctypes.ResultGenesis)
   396  	_, err := c.caller.Call("genesis", map[string]interface{}{}, result)
   397  	if err != nil {
   398  		return nil, errors.Wrap(err, "Genesis")
   399  	}
   400  	return result, nil
   401  }
   402  
   403  func (c *baseRPCClient) Block(height *int64) (*ctypes.ResultBlock, error) {
   404  	result := new(ctypes.ResultBlock)
   405  	_, err := c.caller.Call("block", map[string]interface{}{"height": height}, result)
   406  	if err != nil {
   407  		return nil, errors.Wrap(err, "Block")
   408  	}
   409  	return result, nil
   410  }
   411  
   412  func (c *baseRPCClient) BlockInfo(height *int64) (*types.BlockMeta, error) {
   413  	result := new(types.BlockMeta)
   414  	_, err := c.caller.Call("block_info", map[string]interface{}{"height": height}, result)
   415  	if err != nil {
   416  		return nil, errors.Wrap(err, "BlockInfo")
   417  	}
   418  	return result, nil
   419  }
   420  
   421  func (c *baseRPCClient) BlockResults(height *int64) (*ctypes.ResultBlockResults, error) {
   422  	result := new(ctypes.ResultBlockResults)
   423  	_, err := c.caller.Call("block_results", map[string]interface{}{"height": height}, result)
   424  	if err != nil {
   425  		return nil, errors.Wrap(err, "Block Result")
   426  	}
   427  	return result, nil
   428  }
   429  
   430  func (c *baseRPCClient) Commit(height *int64) (*ctypes.ResultCommit, error) {
   431  	result := new(ctypes.IBCResultCommit)
   432  	_, err := c.caller.Call("commit", map[string]interface{}{"height": height}, result)
   433  	if err != nil {
   434  		return nil, errors.Wrap(err, "Commit")
   435  	}
   436  	return result.ToCommit(), nil
   437  }
   438  
   439  func (c *baseRPCClient) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) {
   440  	result := new(ctypes.ResultTx)
   441  	params := map[string]interface{}{
   442  		"hash":  hash,
   443  		"prove": prove,
   444  	}
   445  	_, err := c.caller.Call("tx", params, result)
   446  	if err != nil {
   447  		return nil, errors.Wrap(err, "Tx")
   448  	}
   449  	return result, nil
   450  }
   451  
   452  func (c *baseRPCClient) TxSearch(query string, prove bool, page, perPage int, orderBy string) (
   453  	*ctypes.ResultTxSearch, error) {
   454  	result := new(ctypes.ResultTxSearch)
   455  	params := map[string]interface{}{
   456  		"query":    query,
   457  		"prove":    prove,
   458  		"page":     page,
   459  		"per_page": perPage,
   460  		"order_by": orderBy,
   461  	}
   462  	_, err := c.caller.Call("tx_search", params, result)
   463  	if err != nil {
   464  		return nil, errors.Wrap(err, "TxSearch")
   465  	}
   466  	return result, nil
   467  }
   468  
   469  func (c *baseRPCClient) Validators(height *int64, page, perPage int) (*ctypes.ResultValidators, error) {
   470  	result := new(ctypes.ResultValidators)
   471  	_, err := c.caller.Call("validators", map[string]interface{}{
   472  		"height":   height,
   473  		"page":     page,
   474  		"per_page": perPage,
   475  	}, result)
   476  	if err != nil {
   477  		return nil, errors.Wrap(err, "Validators")
   478  	}
   479  	return result, nil
   480  }
   481  
   482  func (c *baseRPCClient) BroadcastEvidence(ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) {
   483  	result := new(ctypes.ResultBroadcastEvidence)
   484  	_, err := c.caller.Call("broadcast_evidence", map[string]interface{}{"evidence": ev}, result)
   485  	if err != nil {
   486  		return nil, errors.Wrap(err, "BroadcastEvidence")
   487  	}
   488  	return result, nil
   489  }
   490  
   491  //-----------------------------------------------------------------------------
   492  // WSEvents
   493  
   494  var errNotRunning = errors.New("client is not running. Use .Start() method to start")
   495  
   496  // WSEvents is a wrapper around WSClient, which implements EventsClient.
   497  type WSEvents struct {
   498  	service.BaseService
   499  	cdc      *amino.Codec
   500  	remote   string
   501  	endpoint string
   502  	ws       *jsonrpcclient.WSClient
   503  
   504  	mtx           sync.RWMutex
   505  	subscriptions map[string]chan ctypes.ResultEvent // query -> chan
   506  }
   507  
   508  func newWSEvents(cdc *amino.Codec, remote, endpoint string) (*WSEvents, error) {
   509  	w := &WSEvents{
   510  		cdc:           cdc,
   511  		endpoint:      endpoint,
   512  		remote:        remote,
   513  		subscriptions: make(map[string]chan ctypes.ResultEvent),
   514  	}
   515  	w.BaseService = *service.NewBaseService(nil, "WSEvents", w)
   516  
   517  	var err error
   518  	w.ws, err = jsonrpcclient.NewWS(w.remote, w.endpoint, jsonrpcclient.OnReconnect(func() {
   519  		// resubscribe immediately
   520  		w.redoSubscriptionsAfter(0 * time.Second)
   521  	}))
   522  	if err != nil {
   523  		return nil, err
   524  	}
   525  	w.ws.SetCodec(w.cdc)
   526  	w.ws.SetLogger(w.Logger)
   527  
   528  	return w, nil
   529  }
   530  
   531  // OnStart implements service.Service by starting WSClient and event loop.
   532  func (w *WSEvents) OnStart() error {
   533  	if err := w.ws.Start(); err != nil {
   534  		return err
   535  	}
   536  
   537  	go w.eventListener()
   538  
   539  	return nil
   540  }
   541  
   542  // OnStop implements service.Service by stopping WSClient.
   543  func (w *WSEvents) OnStop() {
   544  	_ = w.ws.Stop()
   545  }
   546  
   547  // Subscribe implements EventsClient by using WSClient to subscribe given
   548  // subscriber to query. By default, returns a channel with cap=1. Error is
   549  // returned if it fails to subscribe.
   550  //
   551  // Channel is never closed to prevent clients from seeing an erroneous event.
   552  //
   553  // It returns an error if WSEvents is not running.
   554  func (w *WSEvents) Subscribe(ctx context.Context, subscriber, query string,
   555  	outCapacity ...int) (out <-chan ctypes.ResultEvent, err error) {
   556  
   557  	if !w.IsRunning() {
   558  		return nil, errNotRunning
   559  	}
   560  
   561  	if err := w.ws.Subscribe(ctx, query); err != nil {
   562  		return nil, err
   563  	}
   564  
   565  	outCap := 1
   566  	if len(outCapacity) > 0 {
   567  		outCap = outCapacity[0]
   568  	}
   569  
   570  	outc := make(chan ctypes.ResultEvent, outCap)
   571  	w.mtx.Lock()
   572  	// subscriber param is ignored because Tendermint will override it with
   573  	// remote IP anyway.
   574  	w.subscriptions[query] = outc
   575  	w.mtx.Unlock()
   576  
   577  	return outc, nil
   578  }
   579  
   580  // Unsubscribe implements EventsClient by using WSClient to unsubscribe given
   581  // subscriber from query.
   582  //
   583  // It returns an error if WSEvents is not running.
   584  func (w *WSEvents) Unsubscribe(ctx context.Context, subscriber, query string) error {
   585  	if !w.IsRunning() {
   586  		return errNotRunning
   587  	}
   588  
   589  	if err := w.ws.Unsubscribe(ctx, query); err != nil {
   590  		return err
   591  	}
   592  
   593  	w.mtx.Lock()
   594  	_, ok := w.subscriptions[query]
   595  	if ok {
   596  		delete(w.subscriptions, query)
   597  	}
   598  	w.mtx.Unlock()
   599  
   600  	return nil
   601  }
   602  
   603  // UnsubscribeAll implements EventsClient by using WSClient to unsubscribe
   604  // given subscriber from all the queries.
   605  //
   606  // It returns an error if WSEvents is not running.
   607  func (w *WSEvents) UnsubscribeAll(ctx context.Context, subscriber string) error {
   608  	if !w.IsRunning() {
   609  		return errNotRunning
   610  	}
   611  
   612  	if err := w.ws.UnsubscribeAll(ctx); err != nil {
   613  		return err
   614  	}
   615  
   616  	w.mtx.Lock()
   617  	w.subscriptions = make(map[string]chan ctypes.ResultEvent)
   618  	w.mtx.Unlock()
   619  
   620  	return nil
   621  }
   622  
   623  // After being reconnected, it is necessary to redo subscription to server
   624  // otherwise no data will be automatically received.
   625  func (w *WSEvents) redoSubscriptionsAfter(d time.Duration) {
   626  	time.Sleep(d)
   627  
   628  	w.mtx.RLock()
   629  	defer w.mtx.RUnlock()
   630  	for q := range w.subscriptions {
   631  		err := w.ws.Subscribe(context.Background(), q)
   632  		if err != nil {
   633  			w.Logger.Error("Failed to resubscribe", "err", err)
   634  		}
   635  	}
   636  }
   637  
   638  func isErrAlreadySubscribed(err error) bool {
   639  	return strings.Contains(err.Error(), tmpubsub.ErrAlreadySubscribed.Error())
   640  }
   641  
   642  func (w *WSEvents) eventListener() {
   643  	for {
   644  		select {
   645  		case resp, ok := <-w.ws.ResponsesCh:
   646  			if !ok {
   647  				return
   648  			}
   649  
   650  			if resp.Error != nil {
   651  				w.Logger.Error("WS error", "err", resp.Error.Error())
   652  				// Error can be ErrAlreadySubscribed or max client (subscriptions per
   653  				// client) reached or Tendermint exited.
   654  				// We can ignore ErrAlreadySubscribed, but need to retry in other
   655  				// cases.
   656  				if !isErrAlreadySubscribed(resp.Error) {
   657  					// Resubscribe after 1 second to give Tendermint time to restart (if
   658  					// crashed).
   659  					w.redoSubscriptionsAfter(1 * time.Second)
   660  				}
   661  				continue
   662  			}
   663  
   664  			result := new(ctypes.ResultEvent)
   665  			err := w.cdc.UnmarshalJSON(resp.Result, result)
   666  			if err != nil {
   667  				w.Logger.Error("failed to unmarshal response", "err", err)
   668  				continue
   669  			}
   670  
   671  			w.mtx.RLock()
   672  			if out, ok := w.subscriptions[result.Query]; ok {
   673  				if cap(out) == 0 {
   674  					out <- *result
   675  				} else {
   676  					select {
   677  					case out <- *result:
   678  					default:
   679  						w.Logger.Error("wanted to publish ResultEvent, but out channel is full", "result", result, "query", result.Query)
   680  					}
   681  				}
   682  			}
   683  			w.mtx.RUnlock()
   684  		case <-w.Quit():
   685  			return
   686  		}
   687  	}
   688  }