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 }