// 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 } }
// 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) } } }
// 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) } } } }
// 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 }
// 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 } } } } }