// handleAbPublish handles Authenticated Broadcast publish requests. // It takes the request as input. func (b Broker) handleAbPublish(pub *pb.Publication) { // fmt.Printf("Handle AB Publish Publication %v, Publisher %v, Broker %v.\n", pub.PublicationID, pub.PublisherID, pub.BrokerID) if b.forwardSent[pub.PublisherID] == nil { b.forwardSent[pub.PublisherID] = make(map[int64]bool) } // If this publication has not been forwarded yet if b.forwardSent[pub.PublisherID][pub.PublicationID] == false { // Update broker ID pub.BrokerID = b.localID // Forward the publication to all subscribers b.subscribersMutex.RLock() for _, subscriber := range b.subscribers { // Only if they are interested in the topic if subscriber.toCh != nil && subscriber.topics[pub.TopicID] == true { subscriber.toCh <- *pub if len(subscriber.toCh) > b.toSubscriberChLen/2 { b.setBusy() } } } b.subscribersMutex.RUnlock() // Mark this publication as sent b.forwardSent[pub.PublisherID][pub.PublicationID] = true // For performance testing, get the time of the last step for this broker b.incrementPublicationCount(pub) } else { // fmt.Printf("Already forwarded publication %v by publisher %v\n", pub.PublicationID, pub.PublisherID) } }
// handleBrbPublish handles Bracha's Reliable Broadcast publish requests. // It takes the request as input. func (b Broker) handleBrbPublish(pub *pb.Publication) { // fmt.Printf("Handle BRB Publish Publication %v, Publisher %v, Broker %v.\n", pub.PublicationID, pub.PublisherID, pub.BrokerID) if b.echoesSent[pub.PublisherID] == nil { b.echoesSent[pub.PublisherID] = make(map[int64]bool) } // If this publication has not been echoed yet if b.echoesSent[pub.PublisherID][pub.PublicationID] == false { // Update broker ID pub.BrokerID = b.localID // "Send" the echo request to itself b.fromBrokerEchoCh <- *pub // Send the echo request to all other brokers b.remoteBrokersMutex.RLock() for _, remoteBroker := range b.remoteBrokers { if remoteBroker.toEchoCh != nil { remoteBroker.toEchoCh <- *pub if len(remoteBroker.toEchoCh) > b.toBrbChLen/2 { b.setBusy() } } } b.remoteBrokersMutex.RUnlock() // Mark this publication as echoed b.echoesSent[pub.PublisherID][pub.PublicationID] = true // fmt.Printf("Sent echoes for publication %v by publisher %v\n", pub.PublicationID, pub.PublisherID) } else { // fmt.Printf("Already sent echoes for publication %v by publisher %v\n", pub.PublicationID, pub.PublisherID) } }
// 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) } } } }
// alterPublication will maliciously alter a publications information. // It returns true if the publication was altered. // It takes as input the publication. func (b *Broker) alterPublication(pub *pb.Publication) pb.Publication { tempPub := pb.Publication{ PubType: pub.PubType, PublisherID: pub.PublisherID, PublicationID: pub.PublicationID, TopicID: pub.TopicID, BrokerID: pub.BrokerID, } for i := range pub.Contents { tempPub.Contents = append(tempPub.Contents, pub.Contents[i]) } for i := range pub.ChainMACs { tempPub.ChainMACs = append(tempPub.ChainMACs, pub.ChainMACs[i]) } r := b.random.Intn(101) if r <= b.maliciousPercent { var alterType int if len(tempPub.ChainMACs) > 0 { alterType = r % 6 } else { alterType = r % 5 } switch alterType { case 0: tempPub.PublicationID = tempPub.PublicationID + 1 case 1: tempPub.PublisherID = tempPub.PublisherID + 1 case 2: tempPub.BrokerID = tempPub.BrokerID + 1 case 3: tempPub.TopicID = tempPub.TopicID + 1 case 4: if len(tempPub.Contents) > 0 { tempPub.Contents[0] = badMessage } case 5: tempPub.ChainMACs = nil } } return tempPub }
// 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) } } }
// handleEcho handles echo requests from Bracha's Reliable Broadcast. // It takes the request as input. func (b Broker) handleEcho(pub *pb.Publication) { // fmt.Printf("Handle echo Publication %v, Publisher %v, Broker %v.\n", pub.PublicationID, pub.PublisherID, pub.BrokerID) // Make the map so not trying to access nil reference if b.echoesReceived[pub.PublisherID] == nil { b.echoesReceived[pub.PublisherID] = make(map[int64]map[uint64]string) } // Make the map so not trying to access nil reference if b.echoesReceived[pub.PublisherID][pub.PublicationID] == nil { b.echoesReceived[pub.PublisherID][pub.PublicationID] = make(map[uint64]string) } // Echo has not been received yet for this publisher ID, publication ID, broker ID if b.echoesReceived[pub.PublisherID][pub.PublicationID][pub.BrokerID] == "" { // So record it b.echoesReceived[pub.PublisherID][pub.PublicationID][pub.BrokerID] = common.GetInfo(pub) // Check if there is a quorum yet for this publisher ID and publication ID foundQuorum := b.checkEchoQuorum(pub.PublisherID, pub.PublicationID) if b.readiesSent[pub.PublisherID] == nil { b.readiesSent[pub.PublisherID] = make(map[int64]bool) } // If this publication has not been readied yet if foundQuorum && b.readiesSent[pub.PublisherID][pub.PublicationID] == false { // Update broker ID pub.BrokerID = b.localID // "Send" the ready request to itself b.fromBrokerReadyCh <- *pub // Send the ready to all other brokers b.remoteBrokersMutex.RLock() for _, remoteBroker := range b.remoteBrokers { if remoteBroker.toReadyCh != nil { remoteBroker.toReadyCh <- *pub if len(remoteBroker.toReadyCh) > b.toBrbChLen/2 { b.setBusy() } } } b.remoteBrokersMutex.RUnlock() // Send the publication to all subscribers b.subscribersMutex.RLock() for _, subscriber := range b.subscribers { // Only if they are interested in the topic if subscriber.toCh != nil && subscriber.topics[pub.TopicID] == true { subscriber.toCh <- *pub if len(subscriber.toCh) > b.toSubscriberChLen/2 { b.setBusy() } } } b.subscribersMutex.RUnlock() // Mark this publication as readied b.readiesSent[pub.PublisherID][pub.PublicationID] = true // fmt.Printf("handleEcho: Sent readies for publication %v by publisher %v.\n", pub.PublicationID, pub.PublisherID) // For performance testing, get the time of the last step for this broker b.incrementPublicationCount(pub) } } }