func (eventHub *EventHub) SetPeerAddr(peerURL string, peerTLSCertificate *sm2.Certificate, peerTLSServerHostOverride string) {
	eventHub.peerAddr = peerURL
	eventHub.peerTLSCertificate = peerTLSCertificate
	eventHub.peerTLSServerHostOverride = peerTLSServerHostOverride
}
SetPeerAddr set peer url for event source
peeraddr peer url
peerTLSCertificate peer tls certificate
peerTLSServerHostOverride tls serverhostoverride
package events
import (
	"reflect"
	"regexp"
	"sync"
	"time"
	"github.com/golang/protobuf/proto"
	"github.com/spf13/cast"
	"google.golang.org/grpc/keepalive"
	"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
	fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
	common "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
	pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
	cnsmr "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/events/consumer"
	"github.com/hyperledger/fabric-sdk-go/pkg/config/urlutil"
	"github.com/hyperledger/fabric-sdk-go/pkg/errors/status"
	consumer "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/events/consumer"
	"github.com/hyperledger/fabric-sdk-go/pkg/logging"
	"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/core/ledger/util"
	"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/utils"
	"github.com/pkg/errors"
	"github.com/hyperledger/fabric-sdk-go/internal/github.com/tjfoc/gmsm/sm2"
)
var logger = logging.NewLogger("fabric_sdk_go")
type EventHub struct {
	mtx sync.RWMutex
	chaincodeRegistrants sync.Map
	blockRegistrants []func(*common.Block)
	txRegistrants sync.Map
	peerAddr string
	peerTLSCertificate *sm2.Certificate
	peerTLSServerHostOverride string
	grpcClient fab.EventsClient
	connected bool
	interestedEvents []*pb.Interest
	eventsClientFactory eventClientFactory
	provider fab.ProviderContext
	identity fab.IdentityContext
	kap      keepalive.ClientParameters
	failFast bool
}
type eventClientFactory interface {
	newEventsClient(provider fab.ProviderContext, identity fab.IdentityContext, peerAddress string, certificate *sm2.Certificate, serverHostOverride string, regTimeout time.Duration, adapter cnsmr.EventAdapter, kap keepalive.ClientParameters, failFast bool) (fab.EventsClient, error)
}
type consumerClientFactory struct{}
func (ccf *consumerClientFactory) newEventsClient(provider fab.ProviderContext, identity fab.IdentityContext, peerAddress string, certificate *sm2.Certificate, serverHostOverride string,
	regTimeout time.Duration, adapter cnsmr.EventAdapter, kap keepalive.ClientParameters, failFast bool) (fab.EventsClient, error) {
	return consumer.NewEventsClient(provider, identity, peerAddress, certificate, serverHostOverride, regTimeout, adapter, kap, failFast)
}
type Context struct {
	fab.ProviderContext
	fab.IdentityContext
}
func New(ctx Context) (*EventHub, error) {
	eventHub := EventHub{
		blockRegistrants:    nil,
		interestedEvents:    nil,
		eventsClientFactory: &consumerClientFactory{},
		provider:            ctx.ProviderContext,
		identity:            ctx.IdentityContext,
	}
	eventHub.RegisterBlockEvent(eventHub.txCallback)
	return &eventHub, nil
}
func FromConfig(ctx Context, peerCfg *apiconfig.PeerConfig) (*EventHub, error) {
	eventHub, err := New(ctx)
	if err != nil {
		return nil, err
	}
	serverHostOverride := ""
	if str, ok := peerCfg.GRPCOptions["ssl-target-name-override"].(string); ok {
		serverHostOverride = str
	}
	eventHub.peerAddr = peerCfg.EventURL
	if urlutil.IsTLSEnabled(eventHub.peerAddr) {
		eventHub.peerTLSCertificate, err = peerCfg.TLSCACerts.TLSCert()
		if err != nil {
			return nil, err
		}
	}
	eventHub.peerTLSServerHostOverride = serverHostOverride
	eventHub.kap = getKeepAliveOptions(peerCfg)
	eventHub.failFast = getFailFast(peerCfg)
	return eventHub, nil
}
func getFailFast(peerCfg *apiconfig.PeerConfig) bool {
	var failFast = true  
	if ff, ok := peerCfg.GRPCOptions["fail-fast"].(bool); ok {
		failFast = cast.ToBool(ff)
	}
	return failFast
}
func getKeepAliveOptions(peerCfg *apiconfig.PeerConfig) keepalive.ClientParameters {
	var kap keepalive.ClientParameters
	if kaTime, ok := peerCfg.GRPCOptions["keep-alive-time"]; ok {
		kap.Time = cast.ToDuration(kaTime)
	}
	if kaTimeout, ok := peerCfg.GRPCOptions["keep-alive-timeout"]; ok {
		kap.Timeout = cast.ToDuration(kaTimeout)
	}
	if kaPermit, ok := peerCfg.GRPCOptions["keep-alive-permit"]; ok {
		kap.PermitWithoutStream = cast.ToBool(kaPermit)
	}
	return kap
}
func (eventHub *EventHub) SetInterests(block bool) {
	eventHub.mtx.Lock()
	defer eventHub.mtx.Unlock()
	eventHub.interestedEvents = make([]*pb.Interest, 0)
	eventHub.blockRegistrants = make([]func(*common.Block), 0)
	if block {
		eventHub.blockRegistrants = append(eventHub.blockRegistrants, eventHub.txCallback)
		eventHub.interestedEvents = append(eventHub.interestedEvents, &pb.Interest{EventType: pb.EventType_BLOCK})
	}
}
func (eventHub *EventHub) Disconnect() error {
	eventHub.mtx.Lock()
	defer eventHub.mtx.Unlock()
	if !eventHub.connected {
		return nil
	}
	err := eventHub.grpcClient.UnregisterAsync(eventHub.interestedEvents)
	if err != nil {
		return errors.WithMessage(err, "event client UnregisterAsync failed")
	}
	err = eventHub.grpcClient.Stop()
	if err != nil {
		return errors.WithMessage(err, "event client stop failed")
	}
	eventHub.connected = false
	return nil
}
func (eventHub *EventHub) RegisterBlockEvent(callback func(*common.Block)) {
	eventHub.mtx.Lock()
	defer eventHub.mtx.Unlock()
	eventHub.blockRegistrants = append(eventHub.blockRegistrants, callback)
	if len(eventHub.blockRegistrants) == 1 {
		eventHub.interestedEvents = append(eventHub.interestedEvents, &pb.Interest{EventType: pb.EventType_BLOCK})
	}
}
func (eventHub *EventHub) UnregisterBlockEvent(callback func(*common.Block)) {
	eventHub.mtx.Lock()
	defer eventHub.mtx.Unlock()
	f1 := reflect.ValueOf(callback)
	for i := range eventHub.blockRegistrants {
		f2 := reflect.ValueOf(eventHub.blockRegistrants[i])
		if f1.Pointer() == f2.Pointer() {
			eventHub.blockRegistrants = append(eventHub.blockRegistrants[:i], eventHub.blockRegistrants[i+1:]...)
			break
		}
	}
	if len(eventHub.blockRegistrants) < 1 {
		blockEventInterest := pb.Interest{EventType: pb.EventType_BLOCK}
		eventHub.grpcClient.UnregisterAsync([]*pb.Interest{&blockEventInterest})
		for i, v := range eventHub.interestedEvents {
			if *v == blockEventInterest {
				eventHub.interestedEvents = append(eventHub.interestedEvents[:i], eventHub.interestedEvents[i+1:]...)
			}
		}
	}
}
func (eventHub *EventHub) addChaincodeInterest(ChaincodeID string, EventName string) {
	ccInterest := &pb.Interest{
		EventType: pb.EventType_CHAINCODE,
		RegInfo: &pb.Interest_ChaincodeRegInfo{
			ChaincodeRegInfo: &pb.ChaincodeReg{
				ChaincodeId: ChaincodeID,
				EventName:   EventName,
			},
		},
	}
	eventHub.interestedEvents = append(eventHub.interestedEvents, ccInterest)
	if eventHub.IsConnected() {
		eventHub.grpcClient.RegisterAsync([]*pb.Interest{ccInterest})
	}
}
func (eventHub *EventHub) removeChaincodeInterest(ChaincodeID string, EventName string) {
	ccInterest := &pb.Interest{
		EventType: pb.EventType_CHAINCODE,
		RegInfo: &pb.Interest_ChaincodeRegInfo{
			ChaincodeRegInfo: &pb.ChaincodeReg{
				ChaincodeId: ChaincodeID,
				EventName:   EventName,
			},
		},
	}
	for i, v := range eventHub.interestedEvents {
		if v.EventType == ccInterest.EventType && *(v.GetChaincodeRegInfo()) == *(ccInterest.GetChaincodeRegInfo()) {
			eventHub.interestedEvents = append(eventHub.interestedEvents[:i], eventHub.interestedEvents[i+1:]...)
		}
	}
	if eventHub.IsConnected() {
		eventHub.grpcClient.UnregisterAsync([]*pb.Interest{ccInterest})
	}
}