Ejemplo n.º 1
0
// startBrokerClient starts an individual broker client.
// It takes as input the broker information.
func (p *Publisher) startBrokerClient(broker brokerInfo) {
	var opts []grpc.DialOption
	opts = append(opts, grpc.WithInsecure(), grpc.WithBlock())

	conn, err := grpc.Dial(broker.addr, opts...)
	if err != nil {
		fmt.Printf("Error while connecting to server: %v\n", err)
		return
	}
	defer conn.Close()

	client := pb.NewPubBrokerClient(conn)
	ch := p.addChannel(broker.id)

	for {
		pub := <-ch
		pub.MAC = common.CreatePublicationMAC(&pub, p.brokers[broker.id].key)

		// Handle publish request and response
		resp, err := client.Publish(context.Background(), &pub)
		if err != nil {
			fmt.Printf("Error publishing to %v, %v\n", broker.id, err)
			p.statusCh <- -1
			continue
		}

		p.statusCh <- resp.Status
	}
}
Ejemplo n.º 2
0
// addMACsRecursive adds MACs to the chain of MACs.
// It takes as input the publication,
// the current node ID string in the tree (should start with the local node's children),
// and the number of generations to add.
func (p *Publisher) addMACs(pub *pb.Publication, currentStr string, generations uint64) {
	if generations > 1 {
		// Add MACs for all the children
		for _, childStr := range p.chainNodes[currentStr].children {
			chainMAC := pb.ChainMAC{
				From: p.localStr,
				To:   childStr,
				MAC:  common.CreatePublicationMAC(pub, p.chainNodes[childStr].key),
			}

			pub.ChainMACs = append(pub.ChainMACs, &chainMAC)

			// Recursively add child macs for next generation
			p.addMACs(pub, childStr, generations-1)
		}
	}
}
Ejemplo n.º 3
0
// addMACsRecursive adds MACs to the chain of MACs. Some older MACs may need to be kept depending
// on the number of generations in the chain.
// It takes as input the new publication,
// the old publication,
// the current node ID string in the tree (should start with the local node's children),
// and the number of generations to add.
func (b *Broker) addMACsRecursive(pub *pb.Publication, oldPub *pb.Publication, currentStr string, generations uint64) {
	// Add any old chain MACs that add going to the child node
	for _, oldChainMAC := range oldPub.ChainMACs {
		if oldChainMAC.To == currentStr {
			pub.ChainMACs = append(pub.ChainMACs, oldChainMAC)
		}
	}

	if generations > 1 {
		// Add MACs for all the broker children
		for _, childStr := range b.chainNodes[currentStr].children {
			addMAC := true

			// Check if the subscriber is subscribed to this topic
			if strings.HasPrefix(childStr, "S") {
				childID, _ := strconv.ParseUint(childStr[1:], 10, 64)
				b.subscribersMutex.RLock()
				if b.subscribers[childID].topics[pub.TopicID] == false {
					// Don't add the MAC is the subscriber isn't interested in this topic
					addMAC = false
				}
				b.subscribersMutex.RUnlock()
			}

			if addMAC {
				chainMAC := pb.ChainMAC{
					From: b.localStr,
					To:   childStr,
					MAC:  common.CreatePublicationMAC(pub, b.chainNodes[childStr].key),
				}

				pub.ChainMACs = append(pub.ChainMACs, &chainMAC)

				// Recursively add child macs for next generation
				b.addMACsRecursive(pub, oldPub, childStr, generations-1)
			}
		}
	}
}
Ejemplo n.º 4
0
// Subscribe handles incoming Subscribe requests from subscribers
func (b *Broker) Subscribe(stream pb.SubBroker_SubscribeServer) error {

	// Read initial subscribe message
	req, err := stream.Recv()
	if err == io.EOF {
		return err
	} else if err != nil {
		return err
	}

	subscriber, exists := b.subscribers[req.SubscriberID]

	// Check MAC
	if !exists || common.CheckSubscriptionMAC(req, req.MAC, subscriber.key) == false {
		fmt.Printf("***BAD MAC: Subscribe*** %v\n", *req)
		return fmt.Errorf("***BAD MAC: Subscribe*** %v\n", *req)
	}

	id := req.SubscriberID
	ch := b.addToSubChannel(id)

	// Add initial subscribe for processing
	b.fromSubscriberCh <- *req

	// Write loop
	go func() {
		for {
			pub := <-ch
			if b.maliciousPercent > 0 {
				if b.maliciousPercent > 100 {
					continue
				} else {
					pub = b.alterPublication(&pub)
				}
			}

			pub.MAC = common.CreatePublicationMAC(&pub, b.subscribers[id].key)
			// fmt.Printf("Send Publication %v, Publisher %v, Broker %v to Subscriber %v.\n", pub.PublicationID, pub.PublisherID, pub.BrokerID, id)

			err := stream.Send(&pub)
			if err != nil {
				b.removeToSubChannel(id)
				break
			}
		}
	}()

	// Read loop
	for {
		req, err := stream.Recv()
		if err == io.EOF {
			b.removeToSubChannel(id)
			return err
		} else if err != nil {
			b.removeToSubChannel(id)
			return err
		}

		// Check MAC
		if common.CheckSubscriptionMAC(req, req.MAC, subscriber.key) == false {
			//fmt.Printf("***BAD MAC: Subscribe*** %v\n", *req)
			continue
		}

		b.fromSubscriberCh <- *req
	}

	return nil
}
Ejemplo n.º 5
0
// connectToBroker connects to a single broker.
// It takes as input the remote broker's ID and address. It also takes as input whether or not
// to be malicous to this remote broker in BRB publications and chain publications.
func (b *Broker) connectToBroker(brokerID uint64, brokerAddr string, brbMalicious bool, chainMalicious bool) {
	fmt.Printf("Trying to connect to %v\n", brokerAddr)
	var opts []grpc.DialOption
	opts = append(opts, grpc.WithInsecure(), grpc.WithBlock())

	// Create a gRPC connection
	conn, err := grpc.Dial(brokerAddr, opts...)
	if err != nil {
		fmt.Printf("Error while connecting to server: %v\n", err)
		return
	}
	defer conn.Close()

	client := pb.NewInterBrokerClient(conn)
	toEchoCh, toReadyCh, toChainCh := b.addBrokerChannels(brokerID)

	// Write loop.
	for {
		select {
		case pub := <-toEchoCh:
			if brbMalicious {
				if b.maliciousPercent > 100 {
					continue
				} else {
					pub = b.alterPublication(&pub)
				}
			}
			pub.MAC = common.CreatePublicationMAC(&pub, b.remoteBrokers[brokerID].key)

			_, err := client.Echo(context.Background(), &pub)
			if err != nil {
			}
		case pub := <-toReadyCh:
			if brbMalicious {
				if b.maliciousPercent > 100 {
					continue
				} else {
					pub = b.alterPublication(&pub)
				}
			}
			pub.MAC = common.CreatePublicationMAC(&pub, b.remoteBrokers[brokerID].key)

			_, err := client.Ready(context.Background(), &pub)
			if err != nil {
			}
		case pub := <-toChainCh:
			if chainMalicious {
				if b.maliciousPercent > 100 {
					continue
				} else {
					pub = b.alterPublication(&pub)
				}
			}
			pub.MAC = common.CreatePublicationMAC(&pub, b.remoteBrokers[brokerID].key)

			for sent := false; sent == false; {
				resp, err := client.Chain(context.Background(), &pub)

				if err != nil {
					sent = false
				} else if resp.Status == pb.ChainResponse_WAIT {
					b.setBusy()
					time.Sleep(100 * time.Microsecond)
					sent = false
				} else {
					sent = true
				}
			}
		}
	}
}