github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/events/producer/handler.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 producer 18 19 import ( 20 "fmt" 21 "strconv" 22 23 "github.com/golang/protobuf/proto" 24 25 "github.com/hyperledger/fabric/msp/mgmt" 26 pb "github.com/hyperledger/fabric/protos/peer" 27 ) 28 29 type handler struct { 30 ChatStream pb.Events_ChatServer 31 interestedEvents map[string]*pb.Interest 32 } 33 34 func newEventHandler(stream pb.Events_ChatServer) (*handler, error) { 35 d := &handler{ 36 ChatStream: stream, 37 } 38 d.interestedEvents = make(map[string]*pb.Interest) 39 return d, nil 40 } 41 42 // Stop stops this handler 43 func (d *handler) Stop() error { 44 d.deregisterAll() 45 d.interestedEvents = nil 46 return nil 47 } 48 49 func getInterestKey(interest pb.Interest) string { 50 var key string 51 switch interest.EventType { 52 case pb.EventType_BLOCK: 53 key = "/" + strconv.Itoa(int(pb.EventType_BLOCK)) 54 case pb.EventType_REJECTION: 55 key = "/" + strconv.Itoa(int(pb.EventType_REJECTION)) 56 case pb.EventType_CHAINCODE: 57 key = "/" + strconv.Itoa(int(pb.EventType_CHAINCODE)) + "/" + interest.GetChaincodeRegInfo().ChaincodeId + "/" + interest.GetChaincodeRegInfo().EventName 58 default: 59 logger.Errorf("unknown interest type %s", interest.EventType) 60 } 61 62 return key 63 } 64 65 func (d *handler) register(iMsg []*pb.Interest) error { 66 // Could consider passing interest array to registerHandler 67 // and only lock once for entire array here 68 for _, v := range iMsg { 69 if err := registerHandler(v, d); err != nil { 70 logger.Errorf("could not register %s: %s", v, err) 71 continue 72 } 73 d.interestedEvents[getInterestKey(*v)] = v 74 } 75 76 return nil 77 } 78 79 func (d *handler) deregister(iMsg []*pb.Interest) error { 80 for _, v := range iMsg { 81 if err := deRegisterHandler(v, d); err != nil { 82 logger.Errorf("could not deregister %s", v) 83 continue 84 } 85 delete(d.interestedEvents, getInterestKey(*v)) 86 } 87 return nil 88 } 89 90 func (d *handler) deregisterAll() { 91 for k, v := range d.interestedEvents { 92 if err := deRegisterHandler(v, d); err != nil { 93 logger.Errorf("could not deregister %s", v) 94 continue 95 } 96 delete(d.interestedEvents, k) 97 } 98 } 99 100 // HandleMessage handles the Openchain messages for the Peer. 101 func (d *handler) HandleMessage(msg *pb.SignedEvent) error { 102 evt, err := validateEventMessage(msg) 103 if err != nil { 104 return fmt.Errorf("event message must be properly signed by an identity from the same organization as the peer: [%s]", err) 105 } 106 107 switch evt.Event.(type) { 108 case *pb.Event_Register: 109 eventsObj := evt.GetRegister() 110 if err := d.register(eventsObj.Events); err != nil { 111 return fmt.Errorf("could not register events %s", err) 112 } 113 case *pb.Event_Unregister: 114 eventsObj := evt.GetUnregister() 115 if err := d.deregister(eventsObj.Events); err != nil { 116 return fmt.Errorf("could not unregister events %s", err) 117 } 118 case nil: 119 default: 120 return fmt.Errorf("invalide type from client %T", evt.Event) 121 } 122 //TODO return supported events.. for now just return the received msg 123 if err := d.ChatStream.Send(evt); err != nil { 124 return fmt.Errorf("error sending response to %v: %s", msg, err) 125 } 126 127 return nil 128 } 129 130 // SendMessage sends a message to the remote PEER through the stream 131 func (d *handler) SendMessage(msg *pb.Event) error { 132 err := d.ChatStream.Send(msg) 133 if err != nil { 134 return fmt.Errorf("error Sending message through ChatStream: %s", err) 135 } 136 return nil 137 } 138 139 // Validates event messages by validating the Creator and verifying 140 // the signature. Returns the unmarshaled Event object 141 // Validation of the creator identity's validity is done by checking with local MSP to ensure the 142 // submitter is a member in the same organization as the peer 143 // 144 // TODO: ideally this should also check each channel's "Readers" policy to ensure the identity satisfies 145 // each channel's access control policy. This step is necessary because the registered listener is going 146 // to get read access to all channels by receiving Block events from all channels. 147 // However, this is not being done for v1.0 due to complexity concerns and the need to complex a stable, 148 // minimally viable release. Eventually events will be made channel-specific, at which point this method 149 // should be revisited 150 func validateEventMessage(signedEvt *pb.SignedEvent) (*pb.Event, error) { 151 logger.Debugf("ValidateEventMessage starts for signed event %p", signedEvt) 152 153 // messages from the client for registering and unregistering must be signed 154 // and accompanied by the signing certificate in the "Creator" field 155 evt := &pb.Event{} 156 err := proto.Unmarshal(signedEvt.EventBytes, evt) 157 if err != nil { 158 return nil, fmt.Errorf("error unmarshaling the event bytes in the SignedEvent: %s", err) 159 } 160 161 localMSP := mgmt.GetLocalMSP() 162 principalGetter := mgmt.NewLocalMSPPrincipalGetter() 163 164 // Load MSPPrincipal for policy 165 principal, err := principalGetter.Get(mgmt.Members) 166 if err != nil { 167 return nil, fmt.Errorf("failed getting local MSP principal [member]: [%s]", err) 168 } 169 170 id, err := localMSP.DeserializeIdentity(evt.Creator) 171 if err != nil { 172 return nil, fmt.Errorf("failed deserializing event creator: [%s]", err) 173 } 174 175 // Verify that event's creator satisfies the principal 176 err = id.SatisfiesPrincipal(principal) 177 if err != nil { 178 return nil, fmt.Errorf("failed verifying the creator satisfies local MSP's [member] principal: [%s]", err) 179 } 180 181 // Verify the signature 182 err = id.Verify(signedEvt.EventBytes, signedEvt.Signature) 183 if err != nil { 184 return nil, fmt.Errorf("failed verifying the event signature: %s", err) 185 } 186 187 return evt, nil 188 }