github.com/Hnampk/fabric@v2.1.1+incompatible/gossip/discovery/discovery_impl.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package discovery 8 9 import ( 10 "bytes" 11 "fmt" 12 "math" 13 "strconv" 14 "strings" 15 "sync" 16 "time" 17 18 proto "github.com/hyperledger/fabric-protos-go/gossip" 19 "github.com/hyperledger/fabric/gossip/common" 20 "github.com/hyperledger/fabric/gossip/gossip/msgstore" 21 "github.com/hyperledger/fabric/gossip/protoext" 22 "github.com/hyperledger/fabric/gossip/util" 23 "github.com/pkg/errors" 24 ) 25 26 const DefAliveTimeInterval = 5 * time.Second 27 const DefAliveExpirationTimeout = 5 * DefAliveTimeInterval 28 const DefAliveExpirationCheckInterval = DefAliveExpirationTimeout / 10 29 const DefReconnectInterval = DefAliveExpirationTimeout 30 const msgExpirationFactor = 20 31 32 var maxConnectionAttempts = 120 33 34 // SetMaxConnAttempts sets the maximum number of connection 35 // attempts the peer would perform when invoking Connect() 36 func SetMaxConnAttempts(attempts int) { 37 maxConnectionAttempts = attempts 38 } 39 40 type timestamp struct { 41 incTime time.Time 42 seqNum uint64 43 lastSeen time.Time 44 } 45 46 func (ts *timestamp) String() string { 47 return fmt.Sprintf("%v, %v", ts.incTime.UnixNano(), ts.seqNum) 48 } 49 50 type gossipDiscoveryImpl struct { 51 incTime uint64 52 seqNum uint64 53 self NetworkMember 54 deadLastTS map[string]*timestamp // H 55 aliveLastTS map[string]*timestamp // V 56 id2Member map[string]*NetworkMember // all known members 57 aliveMembership *util.MembershipStore 58 deadMembership *util.MembershipStore 59 selfAliveMessage *protoext.SignedGossipMessage 60 61 msgStore *aliveMsgStore 62 63 comm CommService 64 crypt CryptoService 65 lock *sync.RWMutex 66 67 toDieChan chan struct{} 68 port int 69 logger util.Logger 70 disclosurePolicy DisclosurePolicy 71 pubsub *util.PubSub 72 73 aliveTimeInterval time.Duration 74 aliveExpirationTimeout time.Duration 75 aliveExpirationCheckInterval time.Duration 76 reconnectInterval time.Duration 77 78 bootstrapPeers []string 79 } 80 81 type DiscoveryConfig struct { 82 AliveTimeInterval time.Duration 83 AliveExpirationTimeout time.Duration 84 AliveExpirationCheckInterval time.Duration 85 ReconnectInterval time.Duration 86 BootstrapPeers []string 87 } 88 89 // NewDiscoveryService returns a new discovery service with the comm module passed and the crypto service passed 90 func NewDiscoveryService(self NetworkMember, comm CommService, crypt CryptoService, disPol DisclosurePolicy, 91 config DiscoveryConfig) Discovery { 92 d := &gossipDiscoveryImpl{ 93 self: self, 94 incTime: uint64(time.Now().UnixNano()), 95 seqNum: uint64(0), 96 deadLastTS: make(map[string]*timestamp), 97 aliveLastTS: make(map[string]*timestamp), 98 id2Member: make(map[string]*NetworkMember), 99 aliveMembership: util.NewMembershipStore(), 100 deadMembership: util.NewMembershipStore(), 101 crypt: crypt, 102 comm: comm, 103 lock: &sync.RWMutex{}, 104 toDieChan: make(chan struct{}), 105 logger: util.GetLogger(util.DiscoveryLogger, self.InternalEndpoint), 106 disclosurePolicy: disPol, 107 pubsub: util.NewPubSub(), 108 109 aliveTimeInterval: config.AliveTimeInterval, 110 aliveExpirationTimeout: config.AliveExpirationTimeout, 111 aliveExpirationCheckInterval: config.AliveExpirationCheckInterval, 112 reconnectInterval: config.ReconnectInterval, 113 114 bootstrapPeers: config.BootstrapPeers, 115 } 116 117 d.validateSelfConfig() 118 d.msgStore = newAliveMsgStore(d) 119 120 go d.periodicalSendAlive() 121 go d.periodicalCheckAlive() 122 go d.handleMessages() 123 go d.periodicalReconnectToDead() 124 go d.handleEvents() 125 126 return d 127 } 128 129 // Lookup returns a network member, or nil if not found 130 func (d *gossipDiscoveryImpl) Lookup(PKIID common.PKIidType) *NetworkMember { 131 if bytes.Equal(PKIID, d.self.PKIid) { 132 return &d.self 133 } 134 d.lock.RLock() 135 defer d.lock.RUnlock() 136 return copyNetworkMember(d.id2Member[string(PKIID)]) 137 } 138 139 func (d *gossipDiscoveryImpl) Connect(member NetworkMember, id identifier) { 140 for _, endpoint := range []string{member.InternalEndpoint, member.Endpoint} { 141 if d.isMyOwnEndpoint(endpoint) { 142 d.logger.Debug("Skipping connecting to myself") 143 return 144 } 145 } 146 147 d.logger.Debug("Entering", member) 148 defer d.logger.Debug("Exiting") 149 go func() { 150 for i := 0; i < maxConnectionAttempts && !d.toDie(); i++ { 151 id, err := id() 152 if err != nil { 153 if d.toDie() { 154 return 155 } 156 d.logger.Warningf("Could not connect to %v : %v", member, err) 157 time.Sleep(d.reconnectInterval) 158 continue 159 } 160 peer := &NetworkMember{ 161 InternalEndpoint: member.InternalEndpoint, 162 Endpoint: member.Endpoint, 163 PKIid: id.ID, 164 } 165 m, err := d.createMembershipRequest(id.SelfOrg) 166 if err != nil { 167 d.logger.Warningf("Failed creating membership request: %+v", errors.WithStack(err)) 168 continue 169 } 170 req, err := protoext.NoopSign(m) 171 if err != nil { 172 d.logger.Warningf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 173 continue 174 } 175 req.Nonce = util.RandomUInt64() 176 req, err = protoext.NoopSign(req.GossipMessage) 177 if err != nil { 178 d.logger.Warningf("Failed adding NONCE to SignedGossipMessage %+v", errors.WithStack(err)) 179 continue 180 } 181 go d.sendUntilAcked(peer, req) 182 return 183 } 184 185 }() 186 } 187 188 func (d *gossipDiscoveryImpl) isMyOwnEndpoint(endpoint string) bool { 189 return endpoint == fmt.Sprintf("127.0.0.1:%d", d.port) || endpoint == fmt.Sprintf("localhost:%d", d.port) || 190 endpoint == d.self.InternalEndpoint || endpoint == d.self.Endpoint 191 } 192 193 func (d *gossipDiscoveryImpl) validateSelfConfig() { 194 endpoint := d.self.InternalEndpoint 195 if len(endpoint) == 0 { 196 d.logger.Panic("Internal endpoint is empty:", endpoint) 197 } 198 199 internalEndpointSplit := strings.Split(endpoint, ":") 200 if len(internalEndpointSplit) != 2 { 201 d.logger.Panicf("Self endpoint %s isn't formatted as 'host:port'", endpoint) 202 } 203 myPort, err := strconv.ParseInt(internalEndpointSplit[1], 10, 64) 204 if err != nil { 205 d.logger.Panicf("Self endpoint %s has not valid port, %+v", endpoint, errors.WithStack(err)) 206 } 207 208 if myPort > int64(math.MaxUint16) { 209 d.logger.Panicf("Self endpoint %s's port takes more than 16 bits", endpoint) 210 } 211 212 d.port = int(myPort) 213 } 214 215 func (d *gossipDiscoveryImpl) sendUntilAcked(peer *NetworkMember, message *protoext.SignedGossipMessage) { 216 nonce := message.Nonce 217 for i := 0; i < maxConnectionAttempts && !d.toDie(); i++ { 218 sub := d.pubsub.Subscribe(fmt.Sprintf("%d", nonce), time.Second*5) 219 d.comm.SendToPeer(peer, message) 220 if _, timeoutErr := sub.Listen(); timeoutErr == nil { 221 return 222 } 223 time.Sleep(d.reconnectInterval) 224 } 225 } 226 227 func (d *gossipDiscoveryImpl) InitiateSync(peerNum int) { 228 if d.toDie() { 229 return 230 } 231 var peers2SendTo []*NetworkMember 232 m, err := d.createMembershipRequest(true) 233 if err != nil { 234 d.logger.Warningf("Failed creating membership request: %+v", errors.WithStack(err)) 235 return 236 } 237 memReq, err := protoext.NoopSign(m) 238 if err != nil { 239 d.logger.Warningf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 240 return 241 } 242 d.lock.RLock() 243 244 n := d.aliveMembership.Size() 245 k := peerNum 246 if k > n { 247 k = n 248 } 249 250 aliveMembersAsSlice := d.aliveMembership.ToSlice() 251 for _, i := range util.GetRandomIndices(k, n-1) { 252 pulledPeer := aliveMembersAsSlice[i].GetAliveMsg().Membership 253 var internalEndpoint string 254 if aliveMembersAsSlice[i].Envelope.SecretEnvelope != nil { 255 internalEndpoint = protoext.InternalEndpoint(aliveMembersAsSlice[i].Envelope.SecretEnvelope) 256 } 257 netMember := &NetworkMember{ 258 Endpoint: pulledPeer.Endpoint, 259 Metadata: pulledPeer.Metadata, 260 PKIid: pulledPeer.PkiId, 261 InternalEndpoint: internalEndpoint, 262 } 263 peers2SendTo = append(peers2SendTo, netMember) 264 } 265 266 d.lock.RUnlock() 267 268 for _, netMember := range peers2SendTo { 269 d.comm.SendToPeer(netMember, memReq) 270 } 271 } 272 273 func (d *gossipDiscoveryImpl) handleEvents() { 274 defer d.logger.Debug("Stopped") 275 276 for { 277 select { 278 case deadPeer := <-d.comm.PresumedDead(): 279 if d.isAlive(deadPeer) { 280 d.expireDeadMembers([]common.PKIidType{deadPeer}) 281 } 282 case changedPKIID := <-d.comm.IdentitySwitch(): 283 // If a peer changed its PKI-ID, purge the old PKI-ID 284 d.purge(changedPKIID) 285 case <-d.toDieChan: 286 return 287 } 288 } 289 } 290 291 func (d *gossipDiscoveryImpl) isAlive(pkiID common.PKIidType) bool { 292 d.lock.RLock() 293 defer d.lock.RUnlock() 294 _, alive := d.aliveLastTS[string(pkiID)] 295 return alive 296 } 297 298 func (d *gossipDiscoveryImpl) handleMessages() { 299 defer d.logger.Debug("Stopped") 300 301 in := d.comm.Accept() 302 for { 303 select { 304 case m := <-in: 305 d.handleMsgFromComm(m) 306 case <-d.toDieChan: 307 return 308 } 309 } 310 } 311 312 func (d *gossipDiscoveryImpl) handleMsgFromComm(msg protoext.ReceivedMessage) { 313 if msg == nil { 314 return 315 } 316 m := msg.GetGossipMessage() 317 if m.GetAliveMsg() == nil && m.GetMemRes() == nil && m.GetMemReq() == nil { 318 d.logger.Warning("Got message with wrong type (expected Alive or MembershipResponse or MembershipRequest message):", m.GossipMessage) 319 return 320 } 321 322 d.logger.Debug("Got message:", m) 323 defer d.logger.Debug("Exiting") 324 325 if memReq := m.GetMemReq(); memReq != nil { 326 selfInfoGossipMsg, err := protoext.EnvelopeToGossipMessage(memReq.SelfInformation) 327 if err != nil { 328 d.logger.Warningf("Failed deserializing GossipMessage from envelope: %+v", errors.WithStack(err)) 329 return 330 } 331 332 if !d.crypt.ValidateAliveMsg(selfInfoGossipMsg) { 333 return 334 } 335 336 if d.msgStore.CheckValid(selfInfoGossipMsg) { 337 d.handleAliveMessage(selfInfoGossipMsg) 338 } 339 340 var internalEndpoint string 341 if m.Envelope.SecretEnvelope != nil { 342 internalEndpoint = protoext.InternalEndpoint(m.Envelope.SecretEnvelope) 343 } 344 345 // Sending a membership response to a peer may block this routine 346 // in case the sending is deliberately slow (i.e attack). 347 // will keep this async until I'll write a timeout detector in the comm layer 348 go d.sendMemResponse(selfInfoGossipMsg.GetAliveMsg().Membership, internalEndpoint, m.Nonce) 349 return 350 } 351 352 if protoext.IsAliveMsg(m.GossipMessage) { 353 if !d.msgStore.CheckValid(m) || !d.crypt.ValidateAliveMsg(m) { 354 return 355 } 356 // If the message was sent by me, ignore it and don't forward it further 357 if d.isSentByMe(m) { 358 return 359 } 360 361 d.msgStore.Add(m) 362 d.handleAliveMessage(m) 363 d.comm.Forward(msg) 364 return 365 } 366 367 if memResp := m.GetMemRes(); memResp != nil { 368 d.pubsub.Publish(fmt.Sprintf("%d", m.Nonce), m.Nonce) 369 for _, env := range memResp.Alive { 370 am, err := protoext.EnvelopeToGossipMessage(env) 371 if err != nil { 372 d.logger.Warningf("Membership response contains an invalid message from an online peer:%+v", errors.WithStack(err)) 373 return 374 } 375 if !protoext.IsAliveMsg(am.GossipMessage) { 376 d.logger.Warning("Expected alive message, got", am, "instead") 377 return 378 } 379 380 if d.msgStore.CheckValid(am) && d.crypt.ValidateAliveMsg(am) { 381 d.handleAliveMessage(am) 382 } 383 } 384 385 for _, env := range memResp.Dead { 386 dm, err := protoext.EnvelopeToGossipMessage(env) 387 if err != nil { 388 d.logger.Warningf("Membership response contains an invalid message from an offline peer %+v", errors.WithStack(err)) 389 return 390 } 391 392 // Newer alive message exists or the message isn't authentic 393 if !d.msgStore.CheckValid(dm) || !d.crypt.ValidateAliveMsg(dm) { 394 continue 395 } 396 397 newDeadMembers := []*protoext.SignedGossipMessage{} 398 d.lock.RLock() 399 if _, known := d.id2Member[string(dm.GetAliveMsg().Membership.PkiId)]; !known { 400 newDeadMembers = append(newDeadMembers, dm) 401 } 402 d.lock.RUnlock() 403 d.learnNewMembers([]*protoext.SignedGossipMessage{}, newDeadMembers) 404 } 405 } 406 } 407 408 func (d *gossipDiscoveryImpl) sendMemResponse(targetMember *proto.Member, internalEndpoint string, nonce uint64) { 409 d.logger.Debug("Entering", protoext.MemberToString(targetMember)) 410 411 targetPeer := &NetworkMember{ 412 Endpoint: targetMember.Endpoint, 413 Metadata: targetMember.Metadata, 414 PKIid: targetMember.PkiId, 415 InternalEndpoint: internalEndpoint, 416 } 417 418 var aliveMsg *protoext.SignedGossipMessage 419 var err error 420 d.lock.RLock() 421 aliveMsg = d.selfAliveMessage 422 d.lock.RUnlock() 423 if aliveMsg == nil { 424 aliveMsg, err = d.createSignedAliveMessage(true) 425 if err != nil { 426 d.logger.Warningf("Failed creating alive message: %+v", errors.WithStack(err)) 427 return 428 } 429 } 430 memResp := d.createMembershipResponse(aliveMsg, targetPeer) 431 if memResp == nil { 432 errMsg := `Got a membership request from a peer that shouldn't have sent one: %v, closing connection to the peer as a result.` 433 d.logger.Warningf(errMsg, targetMember) 434 d.comm.CloseConn(targetPeer) 435 return 436 } 437 438 defer d.logger.Debug("Exiting, replying with", protoext.MembershipResponseToString(memResp)) 439 440 msg, err := protoext.NoopSign(&proto.GossipMessage{ 441 Tag: proto.GossipMessage_EMPTY, 442 Nonce: nonce, 443 Content: &proto.GossipMessage_MemRes{ 444 MemRes: memResp, 445 }, 446 }) 447 if err != nil { 448 err = errors.WithStack(err) 449 d.logger.Warningf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 450 return 451 } 452 d.comm.SendToPeer(targetPeer, msg) 453 } 454 455 func (d *gossipDiscoveryImpl) createMembershipResponse(aliveMsg *protoext.SignedGossipMessage, targetMember *NetworkMember) *proto.MembershipResponse { 456 shouldBeDisclosed, omitConcealedFields := d.disclosurePolicy(targetMember) 457 458 if !shouldBeDisclosed(aliveMsg) { 459 return nil 460 } 461 462 d.lock.RLock() 463 defer d.lock.RUnlock() 464 465 deadPeers := []*proto.Envelope{} 466 467 for _, dm := range d.deadMembership.ToSlice() { 468 469 if !shouldBeDisclosed(dm) { 470 continue 471 } 472 deadPeers = append(deadPeers, omitConcealedFields(dm)) 473 } 474 475 var aliveSnapshot []*proto.Envelope 476 for _, am := range d.aliveMembership.ToSlice() { 477 if !shouldBeDisclosed(am) { 478 continue 479 } 480 aliveSnapshot = append(aliveSnapshot, omitConcealedFields(am)) 481 } 482 483 return &proto.MembershipResponse{ 484 Alive: append(aliveSnapshot, omitConcealedFields(aliveMsg)), 485 Dead: deadPeers, 486 } 487 } 488 489 func (d *gossipDiscoveryImpl) handleAliveMessage(m *protoext.SignedGossipMessage) { 490 d.logger.Debug("Entering", m) 491 defer d.logger.Debug("Exiting") 492 493 if d.isSentByMe(m) { 494 return 495 } 496 497 pkiID := m.GetAliveMsg().Membership.PkiId 498 499 ts := m.GetAliveMsg().Timestamp 500 501 d.lock.RLock() 502 _, known := d.id2Member[string(pkiID)] 503 d.lock.RUnlock() 504 505 if !known { 506 d.learnNewMembers([]*protoext.SignedGossipMessage{m}, []*protoext.SignedGossipMessage{}) 507 return 508 } 509 510 d.lock.RLock() 511 _, isAlive := d.aliveLastTS[string(pkiID)] 512 lastDeadTS, isDead := d.deadLastTS[string(pkiID)] 513 d.lock.RUnlock() 514 515 if !isAlive && !isDead { 516 d.logger.Panicf("Member %s is known but not found neither in alive nor in dead lastTS maps, isAlive=%v, isDead=%v", m.GetAliveMsg().Membership.Endpoint, isAlive, isDead) 517 return 518 } 519 520 if isAlive && isDead { 521 d.logger.Panicf("Member %s is both alive and dead at the same time", m.GetAliveMsg().Membership) 522 return 523 } 524 525 if isDead { 526 if before(lastDeadTS, ts) { 527 // resurrect peer 528 d.resurrectMember(m, *ts) 529 } else if !same(lastDeadTS, ts) { 530 d.logger.Debug("got old alive message about dead peer ", protoext.MemberToString(m.GetAliveMsg().Membership), "lastDeadTS:", lastDeadTS, "but got ts:", ts) 531 } 532 return 533 } 534 535 d.lock.RLock() 536 lastAliveTS, isAlive := d.aliveLastTS[string(pkiID)] 537 d.lock.RUnlock() 538 539 if isAlive { 540 if before(lastAliveTS, ts) { 541 d.learnExistingMembers([]*protoext.SignedGossipMessage{m}) 542 } else if !same(lastAliveTS, ts) { 543 d.logger.Debug("got old alive message about alive peer ", protoext.MemberToString(m.GetAliveMsg().Membership), "lastAliveTS:", lastAliveTS, "but got ts:", ts) 544 } 545 546 } 547 // else, ignore the message because it is too old 548 } 549 550 func (d *gossipDiscoveryImpl) purge(id common.PKIidType) { 551 d.logger.Infof("Purging %s from membership", id) 552 d.lock.Lock() 553 defer d.lock.Unlock() 554 d.aliveMembership.Remove(id) 555 d.deadMembership.Remove(id) 556 delete(d.id2Member, string(id)) 557 delete(d.deadLastTS, string(id)) 558 delete(d.aliveLastTS, string(id)) 559 } 560 561 func (d *gossipDiscoveryImpl) isSentByMe(m *protoext.SignedGossipMessage) bool { 562 pkiID := m.GetAliveMsg().Membership.PkiId 563 if !equalPKIid(pkiID, d.self.PKIid) { 564 return false 565 } 566 d.logger.Debug("Got alive message about ourselves,", m) 567 d.lock.RLock() 568 diffExternalEndpoint := d.self.Endpoint != m.GetAliveMsg().Membership.Endpoint 569 d.lock.RUnlock() 570 var diffInternalEndpoint bool 571 secretEnvelope := m.GetSecretEnvelope() 572 if secretEnvelope != nil { 573 internalEndpoint := protoext.InternalEndpoint(secretEnvelope) 574 if internalEndpoint != "" { 575 diffInternalEndpoint = internalEndpoint != d.self.InternalEndpoint 576 } 577 } 578 if diffInternalEndpoint || diffExternalEndpoint { 579 d.logger.Error("Bad configuration detected: Received AliveMessage from a peer with the same PKI-ID as myself:", m.GossipMessage) 580 } 581 return true 582 } 583 584 func (d *gossipDiscoveryImpl) resurrectMember(am *protoext.SignedGossipMessage, t proto.PeerTime) { 585 d.logger.Debug("Entering, AliveMessage:", am, "t:", t) 586 defer d.logger.Debug("Exiting") 587 d.lock.Lock() 588 defer d.lock.Unlock() 589 590 member := am.GetAliveMsg().Membership 591 pkiID := member.PkiId 592 d.aliveLastTS[string(pkiID)] = ×tamp{ 593 lastSeen: time.Now(), 594 seqNum: t.SeqNum, 595 incTime: tsToTime(t.IncNum), 596 } 597 598 var internalEndpoint string 599 if prevNetMem := d.id2Member[string(pkiID)]; prevNetMem != nil { 600 internalEndpoint = prevNetMem.InternalEndpoint 601 } 602 if am.Envelope.SecretEnvelope != nil { 603 internalEndpoint = protoext.InternalEndpoint(am.Envelope.SecretEnvelope) 604 } 605 606 d.id2Member[string(pkiID)] = &NetworkMember{ 607 Endpoint: member.Endpoint, 608 Metadata: member.Metadata, 609 PKIid: member.PkiId, 610 InternalEndpoint: internalEndpoint, 611 } 612 613 delete(d.deadLastTS, string(pkiID)) 614 d.deadMembership.Remove(common.PKIidType(pkiID)) 615 d.aliveMembership.Put(common.PKIidType(pkiID), &protoext.SignedGossipMessage{GossipMessage: am.GossipMessage, Envelope: am.Envelope}) 616 } 617 618 func (d *gossipDiscoveryImpl) periodicalReconnectToDead() { 619 defer d.logger.Debug("Stopped") 620 621 for !d.toDie() { 622 wg := &sync.WaitGroup{} 623 624 for _, member := range d.copyLastSeen(d.deadLastTS) { 625 wg.Add(1) 626 go func(member NetworkMember) { 627 defer wg.Done() 628 if d.comm.Ping(&member) { 629 d.logger.Debug(member, "is responding, sending membership request") 630 d.sendMembershipRequest(&member, true) 631 } else { 632 d.logger.Debug(member, "is still dead") 633 } 634 }(member) 635 } 636 637 wg.Wait() 638 d.logger.Debug("Sleeping", d.reconnectInterval) 639 time.Sleep(d.reconnectInterval) 640 } 641 } 642 643 func (d *gossipDiscoveryImpl) sendMembershipRequest(member *NetworkMember, includeInternalEndpoint bool) { 644 m, err := d.createMembershipRequest(includeInternalEndpoint) 645 if err != nil { 646 d.logger.Warningf("Failed creating membership request: %+v", errors.WithStack(err)) 647 return 648 } 649 req, err := protoext.NoopSign(m) 650 if err != nil { 651 d.logger.Errorf("Failed creating SignedGossipMessage: %+v", errors.WithStack(err)) 652 return 653 } 654 d.comm.SendToPeer(member, req) 655 } 656 657 func (d *gossipDiscoveryImpl) createMembershipRequest(includeInternalEndpoint bool) (*proto.GossipMessage, error) { 658 am, err := d.createSignedAliveMessage(includeInternalEndpoint) 659 if err != nil { 660 return nil, errors.WithStack(err) 661 } 662 req := &proto.MembershipRequest{ 663 SelfInformation: am.Envelope, 664 // TODO: sending the known peers is not secure because the remote peer might shouldn't know 665 // TODO: about the known peers. I'm deprecating this until a secure mechanism will be implemented. 666 // TODO: See FAB-2570 for tracking this issue. 667 Known: [][]byte{}, 668 } 669 return &proto.GossipMessage{ 670 Tag: proto.GossipMessage_EMPTY, 671 Nonce: uint64(0), 672 Content: &proto.GossipMessage_MemReq{ 673 MemReq: req, 674 }, 675 }, nil 676 } 677 678 func (d *gossipDiscoveryImpl) copyLastSeen(lastSeenMap map[string]*timestamp) []NetworkMember { 679 d.lock.RLock() 680 defer d.lock.RUnlock() 681 682 res := []NetworkMember{} 683 for pkiIDStr := range lastSeenMap { 684 res = append(res, *(d.id2Member[pkiIDStr])) 685 } 686 return res 687 } 688 689 func (d *gossipDiscoveryImpl) periodicalCheckAlive() { 690 defer d.logger.Debug("Stopped") 691 692 for !d.toDie() { 693 time.Sleep(d.aliveExpirationCheckInterval) 694 dead := d.getDeadMembers() 695 if len(dead) > 0 { 696 d.logger.Debugf("Got %v dead members: %v", len(dead), dead) 697 d.expireDeadMembers(dead) 698 } 699 } 700 } 701 702 func (d *gossipDiscoveryImpl) expireDeadMembers(dead []common.PKIidType) { 703 d.logger.Warning("Entering", dead) 704 defer d.logger.Warning("Exiting") 705 706 var deadMembers2Expire []NetworkMember 707 708 d.lock.Lock() 709 710 for _, pkiID := range dead { 711 if _, isAlive := d.aliveLastTS[string(pkiID)]; !isAlive { 712 continue 713 } 714 deadMembers2Expire = append(deadMembers2Expire, d.id2Member[string(pkiID)].Clone()) 715 // move lastTS from alive to dead 716 lastTS, hasLastTS := d.aliveLastTS[string(pkiID)] 717 if hasLastTS { 718 d.deadLastTS[string(pkiID)] = lastTS 719 delete(d.aliveLastTS, string(pkiID)) 720 } 721 722 if am := d.aliveMembership.MsgByID(pkiID); am != nil { 723 d.deadMembership.Put(pkiID, am) 724 d.aliveMembership.Remove(pkiID) 725 } 726 } 727 728 d.lock.Unlock() 729 730 for _, member2Expire := range deadMembers2Expire { 731 d.logger.Warning("Closing connection to", member2Expire) 732 d.comm.CloseConn(&member2Expire) 733 } 734 } 735 736 func (d *gossipDiscoveryImpl) getDeadMembers() []common.PKIidType { 737 d.lock.RLock() 738 defer d.lock.RUnlock() 739 740 dead := []common.PKIidType{} 741 for id, last := range d.aliveLastTS { 742 elapsedNonAliveTime := time.Since(last.lastSeen) 743 if elapsedNonAliveTime > d.aliveExpirationTimeout { 744 d.logger.Warning("Haven't heard from", []byte(id), "for", elapsedNonAliveTime) 745 dead = append(dead, common.PKIidType(id)) 746 } 747 } 748 return dead 749 } 750 751 func (d *gossipDiscoveryImpl) periodicalSendAlive() { 752 defer d.logger.Debug("Stopped") 753 754 for !d.toDie() { 755 d.logger.Debug("Sleeping", d.aliveTimeInterval) 756 time.Sleep(d.aliveTimeInterval) 757 msg, err := d.createSignedAliveMessage(true) 758 if err != nil { 759 d.logger.Warningf("Failed creating alive message: %+v", errors.WithStack(err)) 760 return 761 } 762 d.lock.Lock() 763 d.selfAliveMessage = msg 764 d.lock.Unlock() 765 d.comm.Gossip(msg) 766 } 767 } 768 769 func (d *gossipDiscoveryImpl) aliveMsgAndInternalEndpoint() (*proto.GossipMessage, string) { 770 d.lock.Lock() 771 defer d.lock.Unlock() 772 d.seqNum++ 773 seqNum := d.seqNum 774 endpoint := d.self.Endpoint 775 meta := d.self.Metadata 776 pkiID := d.self.PKIid 777 internalEndpoint := d.self.InternalEndpoint 778 msg := &proto.GossipMessage{ 779 Tag: proto.GossipMessage_EMPTY, 780 Content: &proto.GossipMessage_AliveMsg{ 781 AliveMsg: &proto.AliveMessage{ 782 Membership: &proto.Member{ 783 Endpoint: endpoint, 784 Metadata: meta, 785 PkiId: pkiID, 786 }, 787 Timestamp: &proto.PeerTime{ 788 IncNum: uint64(d.incTime), 789 SeqNum: seqNum, 790 }, 791 }, 792 }, 793 } 794 return msg, internalEndpoint 795 } 796 797 func (d *gossipDiscoveryImpl) createSignedAliveMessage(includeInternalEndpoint bool) (*protoext.SignedGossipMessage, error) { 798 msg, internalEndpoint := d.aliveMsgAndInternalEndpoint() 799 envp := d.crypt.SignMessage(msg, internalEndpoint) 800 if envp == nil { 801 return nil, errors.New("Failed signing message") 802 } 803 signedMsg := &protoext.SignedGossipMessage{ 804 GossipMessage: msg, 805 Envelope: envp, 806 } 807 808 if !includeInternalEndpoint { 809 signedMsg.Envelope.SecretEnvelope = nil 810 } 811 812 return signedMsg, nil 813 } 814 815 func (d *gossipDiscoveryImpl) learnExistingMembers(aliveArr []*protoext.SignedGossipMessage) { 816 d.logger.Debugf("Entering: learnedMembers={%v}", aliveArr) 817 defer d.logger.Debug("Exiting") 818 819 d.lock.Lock() 820 defer d.lock.Unlock() 821 822 for _, m := range aliveArr { 823 am := m.GetAliveMsg() 824 if am == nil { 825 d.logger.Warning("Expected alive message, got instead:", m) 826 return 827 } 828 d.logger.Debug("updating", protoext.AliveMessageToString(am)) 829 830 var internalEndpoint string 831 if prevNetMem := d.id2Member[string(am.Membership.PkiId)]; prevNetMem != nil { 832 internalEndpoint = prevNetMem.InternalEndpoint 833 } 834 if m.Envelope.SecretEnvelope != nil { 835 internalEndpoint = protoext.InternalEndpoint(m.Envelope.SecretEnvelope) 836 } 837 838 // update member's data 839 member := d.id2Member[string(am.Membership.PkiId)] 840 member.Endpoint = am.Membership.Endpoint 841 member.Metadata = am.Membership.Metadata 842 member.InternalEndpoint = internalEndpoint 843 844 if _, isKnownAsDead := d.deadLastTS[string(am.Membership.PkiId)]; isKnownAsDead { 845 d.logger.Warning(am.Membership, "has already expired") 846 continue 847 } 848 849 if _, isKnownAsAlive := d.aliveLastTS[string(am.Membership.PkiId)]; !isKnownAsAlive { 850 d.logger.Warning(am.Membership, "has already expired") 851 continue 852 } else { 853 d.logger.Debug("Updating aliveness data:", protoext.AliveMessageToString(am)) 854 // update existing aliveness data 855 alive := d.aliveLastTS[string(am.Membership.PkiId)] 856 alive.incTime = tsToTime(am.Timestamp.IncNum) 857 alive.lastSeen = time.Now() 858 alive.seqNum = am.Timestamp.SeqNum 859 860 if am := d.aliveMembership.MsgByID(m.GetAliveMsg().Membership.PkiId); am == nil { 861 d.logger.Debug("Adding", am, "to aliveMembership") 862 msg := &protoext.SignedGossipMessage{GossipMessage: m.GossipMessage, Envelope: am.Envelope} 863 d.aliveMembership.Put(m.GetAliveMsg().Membership.PkiId, msg) 864 } else { 865 d.logger.Debug("Replacing", am, "in aliveMembership") 866 am.GossipMessage = m.GossipMessage 867 am.Envelope = m.Envelope 868 } 869 } 870 } 871 } 872 873 func (d *gossipDiscoveryImpl) learnNewMembers(aliveMembers []*protoext.SignedGossipMessage, deadMembers []*protoext.SignedGossipMessage) { 874 d.logger.Debugf("Entering: learnedMembers={%v}, deadMembers={%v}", aliveMembers, deadMembers) 875 defer d.logger.Debugf("Exiting") 876 877 d.lock.Lock() 878 defer d.lock.Unlock() 879 880 for _, am := range aliveMembers { 881 if equalPKIid(am.GetAliveMsg().Membership.PkiId, d.self.PKIid) { 882 continue 883 } 884 d.aliveLastTS[string(am.GetAliveMsg().Membership.PkiId)] = ×tamp{ 885 incTime: tsToTime(am.GetAliveMsg().Timestamp.IncNum), 886 lastSeen: time.Now(), 887 seqNum: am.GetAliveMsg().Timestamp.SeqNum, 888 } 889 890 d.aliveMembership.Put(am.GetAliveMsg().Membership.PkiId, &protoext.SignedGossipMessage{GossipMessage: am.GossipMessage, Envelope: am.Envelope}) 891 d.logger.Debugf("Learned about a new alive member: %v", am) 892 } 893 894 for _, dm := range deadMembers { 895 if equalPKIid(dm.GetAliveMsg().Membership.PkiId, d.self.PKIid) { 896 continue 897 } 898 d.deadLastTS[string(dm.GetAliveMsg().Membership.PkiId)] = ×tamp{ 899 incTime: tsToTime(dm.GetAliveMsg().Timestamp.IncNum), 900 lastSeen: time.Now(), 901 seqNum: dm.GetAliveMsg().Timestamp.SeqNum, 902 } 903 904 d.deadMembership.Put(dm.GetAliveMsg().Membership.PkiId, &protoext.SignedGossipMessage{GossipMessage: dm.GossipMessage, Envelope: dm.Envelope}) 905 d.logger.Debugf("Learned about a new dead member: %v", dm) 906 } 907 908 // update the member in any case 909 for _, a := range [][]*protoext.SignedGossipMessage{aliveMembers, deadMembers} { 910 for _, m := range a { 911 member := m.GetAliveMsg() 912 if member == nil { 913 d.logger.Warning("Expected alive message, got instead:", m) 914 return 915 } 916 917 var internalEndpoint string 918 if m.Envelope.SecretEnvelope != nil { 919 internalEndpoint = protoext.InternalEndpoint(m.Envelope.SecretEnvelope) 920 } 921 922 if prevNetMem := d.id2Member[string(member.Membership.PkiId)]; prevNetMem != nil { 923 internalEndpoint = prevNetMem.InternalEndpoint 924 } 925 926 d.id2Member[string(member.Membership.PkiId)] = &NetworkMember{ 927 Endpoint: member.Membership.Endpoint, 928 Metadata: member.Membership.Metadata, 929 PKIid: member.Membership.PkiId, 930 InternalEndpoint: internalEndpoint, 931 } 932 } 933 } 934 } 935 936 func (d *gossipDiscoveryImpl) GetMembership() []NetworkMember { 937 if d.toDie() { 938 return []NetworkMember{} 939 } 940 d.lock.RLock() 941 defer d.lock.RUnlock() 942 943 response := []NetworkMember{} 944 for _, m := range d.aliveMembership.ToSlice() { 945 member := m.GetAliveMsg() 946 response = append(response, NetworkMember{ 947 PKIid: member.Membership.PkiId, 948 Endpoint: member.Membership.Endpoint, 949 Metadata: member.Membership.Metadata, 950 InternalEndpoint: d.id2Member[string(m.GetAliveMsg().Membership.PkiId)].InternalEndpoint, 951 Envelope: m.Envelope, 952 }) 953 } 954 return response 955 956 } 957 958 func tsToTime(ts uint64) time.Time { 959 return time.Unix(int64(0), int64(ts)) 960 } 961 962 func (d *gossipDiscoveryImpl) UpdateMetadata(md []byte) { 963 d.lock.Lock() 964 defer d.lock.Unlock() 965 d.self.Metadata = md 966 } 967 968 func (d *gossipDiscoveryImpl) UpdateEndpoint(endpoint string) { 969 d.lock.Lock() 970 defer d.lock.Unlock() 971 972 d.self.Endpoint = endpoint 973 } 974 975 func (d *gossipDiscoveryImpl) Self() NetworkMember { 976 var env *proto.Envelope 977 msg, _ := d.aliveMsgAndInternalEndpoint() 978 sMsg, err := protoext.NoopSign(msg) 979 if err != nil { 980 d.logger.Warning("Failed creating SignedGossipMessage:", err) 981 } else { 982 env = sMsg.Envelope 983 } 984 mem := msg.GetAliveMsg().Membership 985 return NetworkMember{ 986 Endpoint: mem.Endpoint, 987 Metadata: mem.Metadata, 988 PKIid: mem.PkiId, 989 Envelope: env, 990 } 991 } 992 993 func (d *gossipDiscoveryImpl) toDie() bool { 994 select { 995 case <-d.toDieChan: 996 return true 997 default: 998 return false 999 } 1000 } 1001 1002 func (d *gossipDiscoveryImpl) Stop() { 1003 select { 1004 case <-d.toDieChan: 1005 default: 1006 close(d.toDieChan) 1007 defer d.logger.Info("Stopped") 1008 d.logger.Info("Stopping") 1009 d.msgStore.Stop() 1010 } 1011 } 1012 1013 func copyNetworkMember(member *NetworkMember) *NetworkMember { 1014 if member == nil { 1015 return nil 1016 } else { 1017 copiedNetworkMember := &NetworkMember{} 1018 *copiedNetworkMember = *member 1019 return copiedNetworkMember 1020 } 1021 } 1022 1023 func equalPKIid(a, b common.PKIidType) bool { 1024 return bytes.Equal(a, b) 1025 } 1026 1027 func same(a *timestamp, b *proto.PeerTime) bool { 1028 return uint64(a.incTime.UnixNano()) == b.IncNum && a.seqNum == b.SeqNum 1029 } 1030 1031 func before(a *timestamp, b *proto.PeerTime) bool { 1032 return (uint64(a.incTime.UnixNano()) == b.IncNum && a.seqNum < b.SeqNum) || 1033 uint64(a.incTime.UnixNano()) < b.IncNum 1034 } 1035 1036 type aliveMsgStore struct { 1037 msgstore.MessageStore 1038 } 1039 1040 func newAliveMsgStore(d *gossipDiscoveryImpl) *aliveMsgStore { 1041 policy := protoext.NewGossipMessageComparator(0) 1042 trigger := func(m interface{}) {} 1043 aliveMsgTTL := d.aliveExpirationTimeout * msgExpirationFactor 1044 externalLock := func() { d.lock.Lock() } 1045 externalUnlock := func() { d.lock.Unlock() } 1046 callback := func(m interface{}) { 1047 msg := m.(*protoext.SignedGossipMessage) 1048 if !protoext.IsAliveMsg(msg.GossipMessage) { 1049 return 1050 } 1051 membership := msg.GetAliveMsg().Membership 1052 id := membership.PkiId 1053 endpoint := membership.Endpoint 1054 internalEndpoint := protoext.InternalEndpoint(msg.SecretEnvelope) 1055 if util.Contains(endpoint, d.bootstrapPeers) || util.Contains(internalEndpoint, d.bootstrapPeers) { 1056 // Never remove a bootstrap peer 1057 return 1058 } 1059 d.logger.Infof("Removing member: Endpoint: %s, InternalEndpoint: %s, PKIID: %x", endpoint, internalEndpoint, id) 1060 d.aliveMembership.Remove(id) 1061 d.deadMembership.Remove(id) 1062 delete(d.id2Member, string(id)) 1063 delete(d.deadLastTS, string(id)) 1064 delete(d.aliveLastTS, string(id)) 1065 } 1066 1067 s := &aliveMsgStore{ 1068 MessageStore: msgstore.NewMessageStoreExpirable(policy, trigger, aliveMsgTTL, externalLock, externalUnlock, callback), 1069 } 1070 return s 1071 } 1072 1073 func (s *aliveMsgStore) Add(msg interface{}) bool { 1074 m := msg.(*protoext.SignedGossipMessage) 1075 if !protoext.IsAliveMsg(m.GossipMessage) { 1076 panic(fmt.Sprint("Msg ", msg, " is not AliveMsg")) 1077 } 1078 return s.MessageStore.Add(msg) 1079 } 1080 1081 func (s *aliveMsgStore) CheckValid(msg interface{}) bool { 1082 m := msg.(*protoext.SignedGossipMessage) 1083 if !protoext.IsAliveMsg(m.GossipMessage) { 1084 panic(fmt.Sprint("Msg ", msg, " is not AliveMsg")) 1085 } 1086 return s.MessageStore.CheckValid(msg) 1087 }