github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/events/consumer/consumer.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package consumer
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"sync"
    24  	"time"
    25  
    26  	"golang.org/x/net/context"
    27  	"google.golang.org/grpc"
    28  
    29  	"github.com/hyperledger/fabric/common/flogging"
    30  	"github.com/hyperledger/fabric/core/comm"
    31  	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
    32  	ehpb "github.com/hyperledger/fabric/protos/peer"
    33  	"github.com/hyperledger/fabric/protos/utils"
    34  )
    35  
    36  var consumerLogger = flogging.MustGetLogger("eventhub_consumer")
    37  
    38  //EventsClient holds the stream and adapter for consumer to work with
    39  type EventsClient struct {
    40  	sync.RWMutex
    41  	peerAddress string
    42  	regTimeout  time.Duration
    43  	stream      ehpb.Events_ChatClient
    44  	adapter     EventAdapter
    45  }
    46  
    47  //NewEventsClient Returns a new grpc.ClientConn to the configured local PEER.
    48  func NewEventsClient(peerAddress string, regTimeout time.Duration, adapter EventAdapter) (*EventsClient, error) {
    49  	var err error
    50  	if regTimeout < 100*time.Millisecond {
    51  		regTimeout = 100 * time.Millisecond
    52  		err = fmt.Errorf("regTimeout >= 0, setting to 100 msec")
    53  	} else if regTimeout > 60*time.Second {
    54  		regTimeout = 60 * time.Second
    55  		err = fmt.Errorf("regTimeout > 60, setting to 60 sec")
    56  	}
    57  	return &EventsClient{sync.RWMutex{}, peerAddress, regTimeout, nil, adapter}, err
    58  }
    59  
    60  //newEventsClientConnectionWithAddress Returns a new grpc.ClientConn to the configured local PEER.
    61  func newEventsClientConnectionWithAddress(peerAddress string) (*grpc.ClientConn, error) {
    62  	if comm.TLSEnabled() {
    63  		return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer())
    64  	}
    65  	return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil)
    66  }
    67  
    68  func (ec *EventsClient) send(emsg *ehpb.Event) error {
    69  	ec.Lock()
    70  	defer ec.Unlock()
    71  
    72  	// obtain the default signing identity for this peer; it will be used to sign the event
    73  	localMsp := mspmgmt.GetLocalMSP()
    74  	if localMsp == nil {
    75  		return errors.New("nil local MSP manager")
    76  	}
    77  
    78  	signer, err := localMsp.GetDefaultSigningIdentity()
    79  	if err != nil {
    80  		return fmt.Errorf("could not obtain the default signing identity, err %s", err)
    81  	}
    82  
    83  	//pass the signer's cert to Creator
    84  	signerCert, err := signer.Serialize()
    85  	if err != nil {
    86  		return fmt.Errorf("fail to serialize the default signing identity, err %s", err)
    87  	}
    88  	emsg.Creator = signerCert
    89  
    90  	signedEvt, err := utils.GetSignedEvent(emsg, signer)
    91  	if err != nil {
    92  		return fmt.Errorf("could not sign outgoing event, err %s", err)
    93  	}
    94  
    95  	return ec.stream.Send(signedEvt)
    96  }
    97  
    98  // RegisterAsync - registers interest in a event and doesn't wait for a response
    99  func (ec *EventsClient) RegisterAsync(ies []*ehpb.Interest) error {
   100  	creator, err := getCreatorFromLocalMSP()
   101  	if err != nil {
   102  		return fmt.Errorf("error getting creator from MSP: %s", err)
   103  	}
   104  	emsg := &ehpb.Event{Event: &ehpb.Event_Register{Register: &ehpb.Register{Events: ies}}, Creator: creator}
   105  
   106  	if err = ec.send(emsg); err != nil {
   107  		consumerLogger.Errorf("error on Register send %s\n", err)
   108  	}
   109  	return err
   110  }
   111  
   112  // register - registers interest in a event
   113  func (ec *EventsClient) register(ies []*ehpb.Interest) error {
   114  	var err error
   115  	if err = ec.RegisterAsync(ies); err != nil {
   116  		return err
   117  	}
   118  
   119  	regChan := make(chan struct{})
   120  	go func() {
   121  		defer close(regChan)
   122  		in, inerr := ec.stream.Recv()
   123  		if inerr != nil {
   124  			err = inerr
   125  			return
   126  		}
   127  		switch in.Event.(type) {
   128  		case *ehpb.Event_Register:
   129  		case nil:
   130  			err = fmt.Errorf("invalid nil object for register")
   131  		default:
   132  			err = fmt.Errorf("invalid registration object")
   133  		}
   134  	}()
   135  	select {
   136  	case <-regChan:
   137  	case <-time.After(ec.regTimeout):
   138  		err = fmt.Errorf("timeout waiting for registration")
   139  	}
   140  	return err
   141  }
   142  
   143  // UnregisterAsync - Unregisters interest in a event and doesn't wait for a response
   144  func (ec *EventsClient) UnregisterAsync(ies []*ehpb.Interest) error {
   145  	creator, err := getCreatorFromLocalMSP()
   146  	if err != nil {
   147  		return fmt.Errorf("error getting creator from MSP: %s", err)
   148  	}
   149  	emsg := &ehpb.Event{Event: &ehpb.Event_Unregister{Unregister: &ehpb.Unregister{Events: ies}}, Creator: creator}
   150  
   151  	if err = ec.send(emsg); err != nil {
   152  		err = fmt.Errorf("error on unregister send %s\n", err)
   153  	}
   154  
   155  	return err
   156  }
   157  
   158  // Recv receives next event - use when client has not called Start
   159  func (ec *EventsClient) Recv() (*ehpb.Event, error) {
   160  	in, err := ec.stream.Recv()
   161  	if err == io.EOF {
   162  		// read done.
   163  		if ec.adapter != nil {
   164  			ec.adapter.Disconnected(nil)
   165  		}
   166  		return nil, err
   167  	}
   168  	if err != nil {
   169  		if ec.adapter != nil {
   170  			ec.adapter.Disconnected(err)
   171  		}
   172  		return nil, err
   173  	}
   174  	return in, nil
   175  }
   176  func (ec *EventsClient) processEvents() error {
   177  	defer ec.stream.CloseSend()
   178  	for {
   179  		in, err := ec.stream.Recv()
   180  		if err == io.EOF {
   181  			// read done.
   182  			if ec.adapter != nil {
   183  				ec.adapter.Disconnected(nil)
   184  			}
   185  			return nil
   186  		}
   187  		if err != nil {
   188  			if ec.adapter != nil {
   189  				ec.adapter.Disconnected(err)
   190  			}
   191  			return err
   192  		}
   193  		if ec.adapter != nil {
   194  			cont, err := ec.adapter.Recv(in)
   195  			if !cont {
   196  				return err
   197  			}
   198  		}
   199  	}
   200  }
   201  
   202  //Start establishes connection with Event hub and registers interested events with it
   203  func (ec *EventsClient) Start() error {
   204  	conn, err := newEventsClientConnectionWithAddress(ec.peerAddress)
   205  	if err != nil {
   206  		return fmt.Errorf("could not create client conn to %s:%s", ec.peerAddress, err)
   207  	}
   208  
   209  	ies, err := ec.adapter.GetInterestedEvents()
   210  	if err != nil {
   211  		return fmt.Errorf("error getting interested events:%s", err)
   212  	}
   213  
   214  	if len(ies) == 0 {
   215  		return fmt.Errorf("must supply interested events")
   216  	}
   217  
   218  	serverClient := ehpb.NewEventsClient(conn)
   219  	ec.stream, err = serverClient.Chat(context.Background())
   220  	if err != nil {
   221  		return fmt.Errorf("could not create client conn to %s:%s", ec.peerAddress, err)
   222  	}
   223  
   224  	if err = ec.register(ies); err != nil {
   225  		return err
   226  	}
   227  
   228  	go ec.processEvents()
   229  
   230  	return nil
   231  }
   232  
   233  //Stop terminates connection with event hub
   234  func (ec *EventsClient) Stop() error {
   235  	if ec.stream == nil {
   236  		// in case the steam/chat server has not been established earlier, we assume that it's closed, successfully
   237  		return nil
   238  	}
   239  	return ec.stream.CloseSend()
   240  }
   241  
   242  func getCreatorFromLocalMSP() ([]byte, error) {
   243  	localMsp := mspmgmt.GetLocalMSP()
   244  	if localMsp == nil {
   245  		return nil, errors.New("nil local MSP manager")
   246  	}
   247  	signer, err := localMsp.GetDefaultSigningIdentity()
   248  	if err != nil {
   249  		return nil, fmt.Errorf("could not obtain the default signing identity, err %s", err)
   250  	}
   251  	creator, err := signer.Serialize()
   252  	if err != nil {
   253  		return nil, fmt.Errorf("error serializing the signer: %s", err)
   254  	}
   255  	return creator, nil
   256  }