Beispiel #1
0
// 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
}
Beispiel #2
0
// 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
}
Beispiel #3
0
// 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
}
Beispiel #4
0
// 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
}