func (wsc *wsConnection) WriteRPCResponse(ctx context.Context, resp rpctypes.RPCResponse) error {
	select {
	case <-wsc.Quit():
		return errors.New("connection was stopped")
	case <-ctx.Done():
		return ctx.Err()
	case wsc.writeChan <- resp:
		return nil
	}
}
WriteRPCResponse pushes a response to the writeChan, and blocks until it is
accepted.
It implements WSRPCConnection. It is Goroutine-safe.
package server
import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"runtime/debug"
	"time"
	"github.com/gorilla/websocket"
	"github.com/tendermint/tendermint/libs/log"
	"github.com/tendermint/tendermint/rpc/client"
	"github.com/tendermint/tendermint/rpc/coretypes"
	rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
)
const (
	defaultWSWriteChanCapacity = 100
	defaultWSWriteWait         = 10 * time.Second
	defaultWSReadWait          = 30 * time.Second
	defaultWSPingPeriod        = (defaultWSReadWait * 9) / 10
)
type WebsocketManager struct {
	websocket.Upgrader
	funcMap       map[string]*RPCFunc
	logger        log.Logger
	wsConnOptions []func(*wsConnection)
}
func NewWebsocketManager(
	funcMap map[string]*RPCFunc,
	wsConnOptions ...func(*wsConnection),
) *WebsocketManager {
	return &WebsocketManager{
		funcMap: funcMap,
		Upgrader: websocket.Upgrader{
			CheckOrigin: func(r *http.Request) bool {
				return true
			},
		},
		logger:        log.NewNopLogger(),
		wsConnOptions: wsConnOptions,
	}
}
func (wm *WebsocketManager) SetLogger(l log.Logger) {
	wm.logger = l
}
func (wm *WebsocketManager) WebsocketHandler(w http.ResponseWriter, r *http.Request) {
	wsConn, err := wm.Upgrade(w, r, nil)
	if err != nil {
		wm.logger.Error("Failed to upgrade connection", "err", err)
		return
	}
	defer func() {
		if err := wsConn.Close(); err != nil {
			wm.logger.Error("Failed to close connection", "err", err)
		}
	}()
	logger := wm.logger.With("remote", wsConn.RemoteAddr())
	con := newWSConnection(wsConn, wm.funcMap, logger, wm.wsConnOptions...)
	wm.logger.Info("New websocket connection", "remote", con.remoteAddr)
	err = con.Start()  
	if err != nil {
		wm.logger.Error("Failed to start connection", "err", err)
		return
	}
	if err := con.Stop(); err != nil {
		wm.logger.Error("error while stopping connection", "error", err)
	}
}
type wsConnection struct {
	*client.RunState
	remoteAddr string
	baseConn   *websocket.Conn
	writeChan chan rpctypes.RPCResponse
	readRoutineQuit chan struct{}
	funcMap map[string]*RPCFunc
	writeChanCapacity int
	writeWait time.Duration
	readWait time.Duration
	pingPeriod time.Duration
	readLimit int64
	onDisconnect func(remoteAddr string)
	ctx    context.Context
	cancel context.CancelFunc
}
func newWSConnection(
	baseConn *websocket.Conn,
	funcMap map[string]*RPCFunc,
	logger log.Logger,
	options ...func(*wsConnection),
) *wsConnection {
	wsc := &wsConnection{
		RunState:          client.NewRunState("wsConnection", logger),
		remoteAddr:        baseConn.RemoteAddr().String(),
		baseConn:          baseConn,
		funcMap:           funcMap,
		writeWait:         defaultWSWriteWait,
		writeChanCapacity: defaultWSWriteChanCapacity,
		readWait:          defaultWSReadWait,
		pingPeriod:        defaultWSPingPeriod,
		readRoutineQuit:   make(chan struct{}),
	}
	for _, option := range options {
		option(wsc)
	}
	wsc.baseConn.SetReadLimit(wsc.readLimit)
	return wsc
}
func OnDisconnect(onDisconnect func(remoteAddr string)) func(*wsConnection) {
	return func(wsc *wsConnection) {
		wsc.onDisconnect = onDisconnect
	}
}
func WriteWait(writeWait time.Duration) func(*wsConnection) {
	return func(wsc *wsConnection) {
		wsc.writeWait = writeWait
	}
}
func WriteChanCapacity(cap int) func(*wsConnection) {
	return func(wsc *wsConnection) {
		wsc.writeChanCapacity = cap
	}
}
func ReadWait(readWait time.Duration) func(*wsConnection) {
	return func(wsc *wsConnection) {
		wsc.readWait = readWait
	}
}
func PingPeriod(pingPeriod time.Duration) func(*wsConnection) {
	return func(wsc *wsConnection) {
		wsc.pingPeriod = pingPeriod
	}
}
func ReadLimit(readLimit int64) func(*wsConnection) {
	return func(wsc *wsConnection) {
		wsc.readLimit = readLimit
	}
}
func (wsc *wsConnection) Start() error {
	if err := wsc.RunState.Start(); err != nil {
		return err
	}
	wsc.writeChan = make(chan rpctypes.RPCResponse, wsc.writeChanCapacity)
	go wsc.readRoutine()
	wsc.writeRoutine()
	return nil
}
func (wsc *wsConnection) Stop() error {
	if err := wsc.RunState.Stop(); err != nil {
		return err
	}
	if wsc.onDisconnect != nil {
		wsc.onDisconnect(wsc.remoteAddr)
	}
	if wsc.ctx != nil {
		wsc.cancel()
	}
	return nil
}
func (wsc *wsConnection) GetRemoteAddr() string {
	return wsc.remoteAddr
}