github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/gossip/comm/comm_impl.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 comm 18 19 import ( 20 "bytes" 21 "crypto/tls" 22 "errors" 23 "fmt" 24 "math/rand" 25 "net" 26 "os" 27 "reflect" 28 "sync" 29 "sync/atomic" 30 "time" 31 32 "github.com/hyperledger/fabric/gossip/api" 33 "github.com/hyperledger/fabric/gossip/common" 34 "github.com/hyperledger/fabric/gossip/identity" 35 "github.com/hyperledger/fabric/gossip/util" 36 proto "github.com/hyperledger/fabric/protos/gossip" 37 "github.com/op/go-logging" 38 "github.com/spf13/viper" 39 "golang.org/x/net/context" 40 "google.golang.org/grpc" 41 "google.golang.org/grpc/credentials" 42 "google.golang.org/grpc/peer" 43 ) 44 45 const ( 46 defDialTimeout = time.Second * time.Duration(3) 47 defConnTimeout = time.Second * time.Duration(2) 48 defRecvBuffSize = 20 49 defSendBuffSize = 20 50 sendOverflowErr = "Send buffer overflow" 51 ) 52 53 var errSendOverflow = errors.New(sendOverflowErr) 54 55 func init() { 56 rand.Seed(42) 57 } 58 59 // SetDialTimeout sets the dial timeout 60 func SetDialTimeout(timeout time.Duration) { 61 viper.Set("peer.gossip.dialTimeout", timeout) 62 } 63 64 func (c *commImpl) SetDialOpts(opts ...grpc.DialOption) { 65 if len(opts) == 0 { 66 c.logger.Warning("Given an empty set of grpc.DialOption, aborting") 67 return 68 } 69 c.opts = opts 70 } 71 72 // NewCommInstanceWithServer creates a comm instance that creates an underlying gRPC server 73 func NewCommInstanceWithServer(port int, idMapper identity.Mapper, peerIdentity api.PeerIdentityType, dialOpts ...grpc.DialOption) (Comm, error) { 74 var ll net.Listener 75 var s *grpc.Server 76 var secOpt grpc.DialOption 77 var certHash []byte 78 79 if len(dialOpts) == 0 { 80 dialOpts = []grpc.DialOption{grpc.WithTimeout(util.GetDurationOrDefault("peer.gossip.dialTimeout", defDialTimeout))} 81 } 82 83 if port > 0 { 84 s, ll, secOpt, certHash = createGRPCLayer(port) 85 dialOpts = append(dialOpts, secOpt) 86 } 87 88 commInst := &commImpl{ 89 selfCertHash: certHash, 90 PKIID: idMapper.GetPKIidOfCert(peerIdentity), 91 idMapper: idMapper, 92 logger: util.GetLogger(util.LoggingCommModule, fmt.Sprintf("%d", port)), 93 peerIdentity: peerIdentity, 94 opts: dialOpts, 95 port: port, 96 lsnr: ll, 97 gSrv: s, 98 msgPublisher: NewChannelDemultiplexer(), 99 lock: &sync.RWMutex{}, 100 deadEndpoints: make(chan common.PKIidType, 100), 101 stopping: int32(0), 102 exitChan: make(chan struct{}, 1), 103 subscriptions: make([]chan proto.ReceivedMessage, 0), 104 blackListedPKIIDs: make([]common.PKIidType, 0), 105 } 106 commInst.connStore = newConnStore(commInst, commInst.logger) 107 commInst.idMapper.Put(idMapper.GetPKIidOfCert(peerIdentity), peerIdentity) 108 109 if port > 0 { 110 go func() { 111 commInst.stopWG.Add(1) 112 defer commInst.stopWG.Done() 113 s.Serve(ll) 114 }() 115 proto.RegisterGossipServer(s, commInst) 116 } 117 118 return commInst, nil 119 } 120 121 // NewCommInstance creates a new comm instance that binds itself to the given gRPC server 122 func NewCommInstance(s *grpc.Server, cert *tls.Certificate, idStore identity.Mapper, peerIdentity api.PeerIdentityType, dialOpts ...grpc.DialOption) (Comm, error) { 123 commInst, err := NewCommInstanceWithServer(-1, idStore, peerIdentity, dialOpts...) 124 if err != nil { 125 return nil, err 126 } 127 128 if cert != nil { 129 inst := commInst.(*commImpl) 130 if len(cert.Certificate) == 0 { 131 inst.logger.Panic("Certificate supplied but certificate chain is empty") 132 } else { 133 inst.selfCertHash = certHashFromRawCert(cert.Certificate[0]) 134 } 135 } 136 137 proto.RegisterGossipServer(s, commInst.(*commImpl)) 138 139 return commInst, nil 140 } 141 142 type commImpl struct { 143 selfCertHash []byte 144 peerIdentity api.PeerIdentityType 145 idMapper identity.Mapper 146 logger *logging.Logger 147 opts []grpc.DialOption 148 connStore *connectionStore 149 PKIID []byte 150 port int 151 deadEndpoints chan common.PKIidType 152 msgPublisher *ChannelDeMultiplexer 153 lock *sync.RWMutex 154 lsnr net.Listener 155 gSrv *grpc.Server 156 exitChan chan struct{} 157 stopping int32 158 stopWG sync.WaitGroup 159 subscriptions []chan proto.ReceivedMessage 160 blackListedPKIIDs []common.PKIidType 161 } 162 163 func (c *commImpl) createConnection(endpoint string, expectedPKIID common.PKIidType) (*connection, error) { 164 var err error 165 var cc *grpc.ClientConn 166 var stream proto.Gossip_GossipStreamClient 167 var pkiID common.PKIidType 168 169 c.logger.Debug("Entering", endpoint, expectedPKIID) 170 defer c.logger.Debug("Exiting") 171 172 if c.isStopping() { 173 return nil, errors.New("Stopping") 174 } 175 cc, err = grpc.Dial(endpoint, append(c.opts, grpc.WithBlock())...) 176 if err != nil { 177 return nil, err 178 } 179 180 cl := proto.NewGossipClient(cc) 181 182 if _, err = cl.Ping(context.Background(), &proto.Empty{}); err != nil { 183 cc.Close() 184 return nil, err 185 } 186 187 if stream, err = cl.GossipStream(context.Background()); err == nil { 188 pkiID, err = c.authenticateRemotePeer(stream) 189 if err == nil { 190 if expectedPKIID != nil && !bytes.Equal(pkiID, expectedPKIID) { 191 // PKIID is nil when we don't know the remote PKI id's 192 c.logger.Warning("Remote endpoint claims to be a different peer, expected", expectedPKIID, "but got", pkiID) 193 return nil, errors.New("Authentication failure") 194 } 195 conn := newConnection(cl, cc, stream, nil) 196 conn.pkiID = pkiID 197 conn.logger = c.logger 198 199 h := func(m *proto.SignedGossipMessage) { 200 c.logger.Debug("Got message:", m) 201 c.msgPublisher.DeMultiplex(&ReceivedMessageImpl{ 202 conn: conn, 203 lock: conn, 204 SignedGossipMessage: m, 205 }) 206 } 207 conn.handler = h 208 return conn, nil 209 } 210 } 211 cc.Close() 212 return nil, err 213 } 214 215 func (c *commImpl) Send(msg *proto.SignedGossipMessage, peers ...*RemotePeer) { 216 if c.isStopping() || len(peers) == 0 { 217 return 218 } 219 220 c.logger.Debug("Entering, sending", msg, "to ", len(peers), "peers") 221 222 for _, peer := range peers { 223 go func(peer *RemotePeer, msg *proto.SignedGossipMessage) { 224 c.sendToEndpoint(peer, msg) 225 }(peer, msg) 226 } 227 } 228 229 func (c *commImpl) BlackListPKIid(PKIID common.PKIidType) { 230 c.logger.Info("Entering", PKIID) 231 defer c.logger.Info("Exiting") 232 c.lock.Lock() 233 defer c.lock.Unlock() 234 c.connStore.closeByPKIid(PKIID) 235 c.blackListedPKIIDs = append(c.blackListedPKIIDs, PKIID) 236 } 237 238 func (c *commImpl) isPKIblackListed(p common.PKIidType) bool { 239 c.lock.RLock() 240 defer c.lock.RUnlock() 241 for _, pki := range c.blackListedPKIIDs { 242 if bytes.Equal(pki, p) { 243 c.logger.Debug(p, ":", true) 244 return true 245 } 246 } 247 c.logger.Debug(p, ":", false) 248 return false 249 } 250 251 func (c *commImpl) sendToEndpoint(peer *RemotePeer, msg *proto.SignedGossipMessage) { 252 if c.isStopping() { 253 return 254 } 255 c.logger.Debug("Entering, Sending to", peer.Endpoint, ", msg:", msg) 256 defer c.logger.Debug("Exiting") 257 var err error 258 259 conn, err := c.connStore.getConnection(peer) 260 if err == nil { 261 disConnectOnErr := func(err error) { 262 c.logger.Warning(peer, "isn't responsive:", err) 263 c.disconnect(peer.PKIID) 264 } 265 conn.send(msg, disConnectOnErr) 266 return 267 } 268 c.logger.Warning("Failed obtaining connection for", peer, "reason:", err) 269 c.disconnect(peer.PKIID) 270 } 271 272 func (c *commImpl) isStopping() bool { 273 return atomic.LoadInt32(&c.stopping) == int32(1) 274 } 275 276 func (c *commImpl) Probe(remotePeer *RemotePeer) error { 277 endpoint := remotePeer.Endpoint 278 pkiID := remotePeer.PKIID 279 if c.isStopping() { 280 return errors.New("Stopping") 281 } 282 c.logger.Debug("Entering, endpoint:", endpoint, "PKIID:", pkiID) 283 cc, err := grpc.Dial(remotePeer.Endpoint, append(c.opts, grpc.WithBlock())...) 284 if err != nil { 285 c.logger.Debug("Returning", err) 286 return err 287 } 288 defer cc.Close() 289 cl := proto.NewGossipClient(cc) 290 _, err = cl.Ping(context.Background(), &proto.Empty{}) 291 c.logger.Debug("Returning", err) 292 return err 293 } 294 295 func (c *commImpl) Accept(acceptor common.MessageAcceptor) <-chan proto.ReceivedMessage { 296 genericChan := c.msgPublisher.AddChannel(acceptor) 297 specificChan := make(chan proto.ReceivedMessage, 10) 298 299 if c.isStopping() { 300 c.logger.Warning("Accept() called but comm module is stopping, returning empty channel") 301 return specificChan 302 } 303 304 c.lock.Lock() 305 c.subscriptions = append(c.subscriptions, specificChan) 306 c.lock.Unlock() 307 308 go func() { 309 defer c.logger.Debug("Exiting Accept() loop") 310 defer func() { 311 c.logger.Warning("Recovered") 312 recover() 313 }() 314 315 c.stopWG.Add(1) 316 defer c.stopWG.Done() 317 318 for { 319 select { 320 case msg := <-genericChan: 321 specificChan <- msg.(*ReceivedMessageImpl) 322 break 323 case s := <-c.exitChan: 324 c.exitChan <- s 325 return 326 } 327 } 328 }() 329 return specificChan 330 } 331 332 func (c *commImpl) PresumedDead() <-chan common.PKIidType { 333 return c.deadEndpoints 334 } 335 336 func (c *commImpl) CloseConn(peer *RemotePeer) { 337 c.logger.Debug("Closing connection for", peer) 338 c.connStore.closeConn(peer) 339 } 340 341 func (c *commImpl) emptySubscriptions() { 342 c.lock.Lock() 343 defer c.lock.Unlock() 344 for _, ch := range c.subscriptions { 345 close(ch) 346 } 347 } 348 349 func (c *commImpl) Stop() { 350 if c.isStopping() { 351 return 352 } 353 atomic.StoreInt32(&c.stopping, int32(1)) 354 c.logger.Info("Stopping") 355 defer c.logger.Info("Stopped") 356 if c.gSrv != nil { 357 c.gSrv.Stop() 358 } 359 if c.lsnr != nil { 360 c.lsnr.Close() 361 } 362 c.connStore.shutdown() 363 c.logger.Debug("Shut down connection store, connection count:", c.connStore.connNum()) 364 c.exitChan <- struct{}{} 365 c.msgPublisher.Close() 366 c.logger.Debug("Shut down publisher") 367 c.emptySubscriptions() 368 c.logger.Debug("Closed subscriptions, waiting for goroutines to stop...") 369 c.stopWG.Wait() 370 } 371 372 func (c *commImpl) GetPKIid() common.PKIidType { 373 return c.PKIID 374 } 375 376 func extractRemoteAddress(stream stream) string { 377 var remoteAddress string 378 p, ok := peer.FromContext(stream.Context()) 379 if ok { 380 if address := p.Addr; address != nil { 381 remoteAddress = address.String() 382 } 383 } 384 return remoteAddress 385 } 386 387 func (c *commImpl) authenticateRemotePeer(stream stream) (common.PKIidType, error) { 388 ctx := stream.Context() 389 remoteAddress := extractRemoteAddress(stream) 390 remoteCertHash := extractCertificateHashFromContext(ctx) 391 var err error 392 var cMsg *proto.SignedGossipMessage 393 var signer proto.Signer 394 395 // If TLS is detected, sign the hash of our cert to bind our TLS cert 396 // to the gRPC session 397 if remoteCertHash != nil && c.selfCertHash != nil { 398 signer = func(msg []byte) ([]byte, error) { 399 return c.idMapper.Sign(msg) 400 } 401 } else { // If we don't use TLS, we have no unique text to sign, 402 // so don't sign anything 403 signer = func(msg []byte) ([]byte, error) { 404 return msg, nil 405 } 406 } 407 408 cMsg = c.createConnectionMsg(c.PKIID, c.selfCertHash, c.peerIdentity, signer) 409 410 c.logger.Debug("Sending", cMsg, "to", remoteAddress) 411 stream.Send(cMsg.Envelope) 412 m, err := readWithTimeout(stream, util.GetDurationOrDefault("peer.gossip.connTimeout", defConnTimeout), remoteAddress) 413 if err != nil { 414 err := fmt.Errorf("Failed reading messge from %s, reason: %v", remoteAddress, err) 415 c.logger.Warning(err) 416 return nil, err 417 } 418 receivedMsg := m.GetConn() 419 if receivedMsg == nil { 420 c.logger.Warning("Expected connection message but got", receivedMsg) 421 return nil, errors.New("Wrong type") 422 } 423 424 if receivedMsg.PkiID == nil { 425 c.logger.Warning("%s didn't send a pkiID") 426 return nil, fmt.Errorf("%s didn't send a pkiID", remoteAddress) 427 } 428 429 if c.isPKIblackListed(receivedMsg.PkiID) { 430 c.logger.Warning("Connection attempt from", remoteAddress, "but it is black-listed") 431 return nil, errors.New("Black-listed") 432 } 433 c.logger.Debug("Received", receivedMsg, "from", remoteAddress) 434 err = c.idMapper.Put(receivedMsg.PkiID, receivedMsg.Cert) 435 if err != nil { 436 c.logger.Warning("Identity store rejected", remoteAddress, ":", err) 437 return nil, err 438 } 439 440 // if TLS is detected, verify remote peer 441 if remoteCertHash != nil && c.selfCertHash != nil { 442 if !bytes.Equal(remoteCertHash, receivedMsg.Hash) { 443 return nil, fmt.Errorf("Expected %v in remote hash, but got %v", remoteCertHash, receivedMsg.Hash) 444 } 445 verifier := func(peerIdentity []byte, signature, message []byte) error { 446 pkiID := c.idMapper.GetPKIidOfCert(api.PeerIdentityType(peerIdentity)) 447 return c.idMapper.Verify(pkiID, signature, message) 448 } 449 err = m.Verify(receivedMsg.Cert, verifier) 450 if err != nil { 451 c.logger.Error("Failed verifying signature from", remoteAddress, ":", err) 452 return nil, err 453 } 454 } 455 456 c.logger.Debug("Authenticated", remoteAddress) 457 return receivedMsg.PkiID, nil 458 } 459 460 func (c *commImpl) GossipStream(stream proto.Gossip_GossipStreamServer) error { 461 if c.isStopping() { 462 return errors.New("Shutting down") 463 } 464 PKIID, err := c.authenticateRemotePeer(stream) 465 if err != nil { 466 c.logger.Error("Authentication failed") 467 return err 468 } 469 c.logger.Debug("Servicing", extractRemoteAddress(stream)) 470 471 conn := c.connStore.onConnected(stream, PKIID) 472 473 // if connStore denied the connection, it means we already have a connection to that peer 474 // so close this stream 475 if conn == nil { 476 return nil 477 } 478 479 h := func(m *proto.SignedGossipMessage) { 480 c.msgPublisher.DeMultiplex(&ReceivedMessageImpl{ 481 conn: conn, 482 lock: conn, 483 SignedGossipMessage: m, 484 }) 485 } 486 487 conn.handler = h 488 489 defer func() { 490 c.logger.Debug("Client", extractRemoteAddress(stream), " disconnected") 491 c.connStore.closeByPKIid(PKIID) 492 conn.close() 493 }() 494 495 return conn.serviceConnection() 496 } 497 498 func (c *commImpl) Ping(context.Context, *proto.Empty) (*proto.Empty, error) { 499 return &proto.Empty{}, nil 500 } 501 502 func (c *commImpl) disconnect(pkiID common.PKIidType) { 503 if c.isStopping() { 504 return 505 } 506 c.deadEndpoints <- pkiID 507 c.connStore.closeByPKIid(pkiID) 508 } 509 510 func readWithTimeout(stream interface{}, timeout time.Duration, address string) (*proto.SignedGossipMessage, error) { 511 incChan := make(chan *proto.SignedGossipMessage, 1) 512 errChan := make(chan error, 1) 513 go func() { 514 if srvStr, isServerStr := stream.(proto.Gossip_GossipStreamServer); isServerStr { 515 if m, err := srvStr.Recv(); err == nil { 516 msg, err := m.ToGossipMessage() 517 if err != nil { 518 errChan <- err 519 return 520 } 521 incChan <- msg 522 } 523 } else if clStr, isClientStr := stream.(proto.Gossip_GossipStreamClient); isClientStr { 524 if m, err := clStr.Recv(); err == nil { 525 msg, err := m.ToGossipMessage() 526 if err != nil { 527 errChan <- err 528 return 529 } 530 incChan <- msg 531 } 532 } else { 533 panic(fmt.Errorf("Stream isn't a GossipStreamServer or a GossipStreamClient, but %v. Aborting", reflect.TypeOf(stream))) 534 } 535 }() 536 select { 537 case <-time.NewTicker(timeout).C: 538 return nil, fmt.Errorf("Timed out waiting for connection message from %s", address) 539 case m := <-incChan: 540 return m, nil 541 case err := <-errChan: 542 return nil, err 543 } 544 } 545 546 func (c *commImpl) createConnectionMsg(pkiID common.PKIidType, hash []byte, cert api.PeerIdentityType, signer proto.Signer) *proto.SignedGossipMessage { 547 m := &proto.GossipMessage{ 548 Tag: proto.GossipMessage_EMPTY, 549 Nonce: 0, 550 Content: &proto.GossipMessage_Conn{ 551 Conn: &proto.ConnEstablish{ 552 Hash: hash, 553 Cert: cert, 554 PkiID: pkiID, 555 }, 556 }, 557 } 558 sMsg := &proto.SignedGossipMessage{ 559 GossipMessage: m, 560 } 561 sMsg.Sign(signer) 562 return sMsg 563 } 564 565 type stream interface { 566 Send(envelope *proto.Envelope) error 567 Recv() (*proto.Envelope, error) 568 grpc.Stream 569 } 570 571 func createGRPCLayer(port int) (*grpc.Server, net.Listener, grpc.DialOption, []byte) { 572 var returnedCertHash []byte 573 var s *grpc.Server 574 var ll net.Listener 575 var err error 576 var serverOpts []grpc.ServerOption 577 var dialOpts grpc.DialOption 578 579 keyFileName := fmt.Sprintf("key.%d.pem", rand.Int63()) 580 certFileName := fmt.Sprintf("cert.%d.pem", rand.Int63()) 581 582 defer os.Remove(keyFileName) 583 defer os.Remove(certFileName) 584 585 err = generateCertificates(keyFileName, certFileName) 586 if err == nil { 587 cert, err := tls.LoadX509KeyPair(certFileName, keyFileName) 588 if err != nil { 589 panic(err) 590 } 591 592 if len(cert.Certificate) == 0 { 593 panic(errors.New("Certificate chain is nil")) 594 } 595 596 returnedCertHash = certHashFromRawCert(cert.Certificate[0]) 597 598 tlsConf := &tls.Config{ 599 Certificates: []tls.Certificate{cert}, 600 ClientAuth: tls.RequestClientCert, 601 InsecureSkipVerify: true, 602 } 603 serverOpts = append(serverOpts, grpc.Creds(credentials.NewTLS(tlsConf))) 604 ta := credentials.NewTLS(&tls.Config{ 605 Certificates: []tls.Certificate{cert}, 606 InsecureSkipVerify: true, 607 }) 608 dialOpts = grpc.WithTransportCredentials(&authCreds{tlsCreds: ta}) 609 } else { 610 dialOpts = grpc.WithInsecure() 611 } 612 613 listenAddress := fmt.Sprintf("%s:%d", "", port) 614 ll, err = net.Listen("tcp", listenAddress) 615 if err != nil { 616 panic(err) 617 } 618 619 s = grpc.NewServer(serverOpts...) 620 return s, ll, dialOpts, returnedCertHash 621 }