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