// Ready handles incoming BRB ready requests from other brokers func (b *Broker) Ready(ctx context.Context, pub *pb.Publication) (*pb.ReadyResponse, error) { remoteBroker, exists := b.remoteBrokers[pub.BrokerID] // Check MAC if !exists || common.CheckPublicationMAC(pub, pub.MAC, remoteBroker.key) == false { // fmt.Printf("***BAD MAC: Ready*** %v\n", pub) return &pb.ReadyResponse{Status: pb.ReadyResponse_BAD_MAC}, nil } b.fromBrokerReadyCh <- *pub return &pb.ReadyResponse{Status: pb.ReadyResponse_OK}, nil }
// verifyChainMACsRecursive verifies the MACs for the Chain algorithm. // It returns true if the MACs in the chain are verified. // It takes as input the publication, // the current node ID string in the tree (should start with the local node), // and the number of generations to check. func (b *Broker) verifyChainMACsRecursive(pub *pb.Publication, currentStr string, generations uint64) bool { // Nothing to check, no parents if len(b.chainNodes[currentStr].parents) == 0 { return true } // If still in the chain range if generations > 0 { foundMatch := false // Look through this node's parents and in the list of Chain MACs // for a matching set of Tos and Froms for _, parentStr := range b.chainNodes[currentStr].parents { for _, chainMAC := range pub.ChainMACs { if chainMAC.To == b.localStr && chainMAC.From == parentStr { foundMatch = true // Actually check the MAC here. if common.CheckPublicationMAC(pub, chainMAC.MAC, b.chainNodes[parentStr].key) == false { //fmt.Printf("***BAD MAC: Chain*** %v\n", *pub) return false } // Go back one more generation verified := b.verifyChainMACsRecursive(pub, parentStr, generations-1) if verified { return true } } } } // If couldn't find a MAC for this generation. if foundMatch == false { //fmt.Printf("***MISSING MAC: Chain*** %v\n", *pub) return false } } else { // No longer in the chain range, so all the MACs matched. return true } // Not all the MACs in the chain were verified. return false }
// Chain handles incoming Chain requests from other brokers func (b *Broker) Chain(ctx context.Context, pub *pb.Publication) (*pb.ChainResponse, error) { if b.isBusy { return &pb.ChainResponse{Status: pb.ChainResponse_WAIT}, nil } remoteBroker, exists := b.remoteBrokers[pub.BrokerID] // Check MAC if !exists || common.CheckPublicationMAC(pub, pub.MAC, remoteBroker.key) == false { // fmt.Printf("***BAD MAC: Chain*** %v\n", *pub) return &pb.ChainResponse{Status: pb.ChainResponse_BAD_MAC}, nil } b.fromBrokerChainCh <- *pub return &pb.ChainResponse{Status: pb.ChainResponse_OK}, nil }
// Publish handles incoming Publish requests from publishers func (b *Broker) Publish(ctx context.Context, pub *pb.Publication) (*pb.PubResponse, error) { if b.isBusy { return &pb.PubResponse{Status: pb.PubResponse_WAIT}, nil } publisher, exists := b.publishers[pub.PublisherID] // Check MAC if !exists || common.CheckPublicationMAC(pub, pub.MAC, publisher.key) == false { fmt.Printf("***BAD MAC: Publish*** %v\n", *pub) return &pb.PubResponse{Status: pb.PubResponse_BAD_MAC}, nil } // If using alpha values (indicating a combination of algorithms) if b.alpha > 0 { if b.alphaCounters[pub.PublisherID] == nil { b.alphaCounters[pub.PublisherID] = make(map[uint64]uint64) } if pub.PubType == common.BRB { b.fromPublisherCh <- *pub b.alphaCounters[pub.PublisherID][pub.TopicID] = 0 } else { // Don't allow more than 2 * alpha publications for a topic and publisher without a history request if b.alphaCounters[pub.PublisherID][pub.TopicID] >= 2*b.alpha { return &pb.PubResponse{Status: pb.PubResponse_BLOCKED}, nil } b.fromPublisherCh <- *pub b.alphaCounters[pub.PublisherID][pub.TopicID]++ if b.alphaCounters[pub.PublisherID][pub.TopicID] >= b.alpha { return &pb.PubResponse{Status: pb.PubResponse_HISTORY}, nil } } } else { b.fromPublisherCh <- *pub } return &pb.PubResponse{Status: pb.PubResponse_OK}, nil }
// startBrokerClient starts an individual broker clients. It takes as input // broker information. func (s *Subscriber) startBrokerClient(broker brokerInfo) bool { var opts []grpc.DialOption opts = append(opts, grpc.WithInsecure()) conn, err := grpc.Dial(broker.addr, opts...) if err != nil { fmt.Printf("Error while connecting to server: %v\n", err) return false } client := pb.NewSubBrokerClient(conn) stream, err := client.Subscribe(context.Background()) if err != nil { fmt.Printf("Error while starting the Subscribe stream: %v\n", err) return false } var topics []uint64 for i := range s.topics { topics = append(topics, i) } ch := s.addChannel(broker.id) // Write loop go func() { for { subReq := <-ch mac := common.CreateSubscriptionMAC(&subReq, broker.key) subReq.MAC = mac err = stream.Send(&subReq) if err != nil { return } } }() // Read loop go func() { for { pub, err := stream.Recv() // fmt.Printf("Received publication %v from publisher %v and broker %v.\n", pub.PublicationID, pub.PublisherID, pub.BrokerID) if err == io.EOF { s.removeChannel(broker.id) break } if err != nil { s.removeChannel(broker.id) break } tempBroker, exists := s.brokers[pub.BrokerID] if !exists || common.CheckPublicationMAC(pub, pub.MAC, tempBroker.key) == false { //fmt.Printf("***BAD MAC: Chain*** %v\n", *pub) continue } s.fromBrokerCh <- *pub } }() // Send the initial subscribe request. subReq := pb.SubRequest{ SubscriberID: s.localID, TopicIDs: topics, } mac := common.CreateSubscriptionMAC(&subReq, broker.key) subReq.MAC = mac ch <- subReq return true }