def check_timer(self, eventobj: Event): current_time = datetime.datetime.now() delta = current_time - self.waiting_since if delta.seconds > self.timeout_duration: self.send_self(Event(self, FireWirePacketType.TIMEOUT, "...")) else: sleep(0.2) self.send_self(Event(self, FireWirePacketType.CHECK_TIMER, "..."))
def on_message_from_bottom(self, eventobj: Event): applmessage = eventobj.eventcontent hdr = applmessage.header # print(f"Node-{self.componentinstancenumber}: Node-{hdr.messagefrom} has sent {hdr.messagetype} message (payload: {applmessage.payload})") if hdr.messagetype == ApplicationLayerMessageType.BASIC: self.basic_message_queue.put_nowait(applmessage) if self._in_tree: self.send_ack_control_message(hdr.messagefrom, False) else: self._parent_node = hdr.messagefrom self._in_tree = True if self.componentinstancenumber not in self.context["alive_nodes"]: self.context["alive_nodes"].append(self.componentinstancenumber) elif hdr.messagetype == ApplicationLayerMessageType.CONTROL: # self.control_message_queue.put_nowait(applmessage) try: self._children.remove(hdr.messagefrom) self._child_counter -= 1 except ValueError as e: # print(f"\n\n\n{self.componentinstancenumber}: {e} {hdr.messagefrom} {self._children}\n\n\n") pass elif hdr.messagetype == ApplicationLayerMessageType.WAVE: if applmessage.payload.messagepayload.tag == self.componentinstancenumber: self.my_wave_bucket.append(applmessage.payload.messagepayload.response) if WAVE_DEBUG: print(f" WAVE << N-{self.componentinstancenumber} << N-{hdr.messagefrom} ({applmessage.payload.messagepayload.response})") if len(self.my_wave_bucket) == (len(self.context["network"].G.nodes()) - 1): if WAVE_DEBUG: print(f" ::: WAVE END >> N-{self.componentinstancenumber}: {' '.join(['A' if x == SFWaveResponse.ACTIVE else ('F' if x == SFWaveResponse.FINISHED else 'XXX') for x in self.my_wave_bucket])}") if SFWaveResponse.ACTIVE not in self.my_wave_bucket: print(f" ::: WAVE END >> N-{self.componentinstancenumber}: ANNOUNCE!") self.announce_on_next_tick = True else: print(f" ::: WAVE END >> N-{self.componentinstancenumber}: NOT DONE YET!") self.my_wave_bucket = [] else: if self.__exited_from_tree: self.send_down(Event(self, EventTypes.MFRT, self.prepare_application_layer_message(ApplicationLayerMessageType.WAVE, applmessage.payload.messagepayload.tag, SFWaveMessagePayload(applmessage.payload.messagepayload.tag, SFWaveMessageType.RESPONSE, SFWaveResponse.FINISHED)))) if WAVE_DEBUG: print(f" WAVE >> N-{self.componentinstancenumber} >> N-{applmessage.payload.messagepayload.tag} >> FINISHED") else: self.send_down(Event(self, EventTypes.MFRT, self.prepare_application_layer_message(ApplicationLayerMessageType.WAVE, applmessage.payload.messagepayload.tag, SFWaveMessagePayload(applmessage.payload.messagepayload.tag, SFWaveMessageType.RESPONSE, SFWaveResponse.ACTIVE)))) if WAVE_DEBUG: print(f" WAVE >> N-{self.componentinstancenumber} >> N-{applmessage.payload.messagepayload.tag} >> ACTIVE") self._wms += 1 else: print(f"\n!!! N-{self.componentinstancenumber}: GOT MSG UNIDENT: {hdr.messagetype}, FROM {hdr.messagefrom}") sys.exit(2)
def on_tx_alive_message(self, eventobj: Event): time.sleep(self.alivemessageperiod) # Period of alive messages # Send down the I'm Alive mesage # print("I am alive....") hdr = FailureDetectorMessageHeader( FailureDetectorMessageTypes.IAMALIVE, self.componentinstancenumber, MessageDestinationIdentifiers.LINKLAYERBROADCAST) payload = FailureDetectorMessagePayload( f"I am Node.{self.componentinstancenumber} and I am live ") failuredetectormessage = GenericMessage(hdr, payload) self.send_down(Event(self, EventTypes.MFRT, failuredetectormessage)) # Schedule the next I'm Alive message self.send_self(Event(self, "txalivemessage", "timer for alive message"))
def on_message_from_bottom(self, eventobj: Event): """ New message from the link layer """ header: FireWireMessageHeader = eventobj.eventcontent.header # paylaod is not important for FireWire if header.messagetype == FireWirePacketType.PARENT_REQ: if header.messagefrom is not self.parent: new_child = header.messagefrom self.received.append(new_child) next_hop_interface_id = f"{self.componentinstancenumber}-{new_child}" header = FireWireMessageHeader( messagefrom=self.componentinstancenumber, messageto=new_child, nexthop=new_child, messagetype=FireWirePacketType.ACKNOWLEDGEMENT, interfaceid=next_hop_interface_id, ) payload = FireWireMessagePayload() ack = GenericMessage(header, payload) self.send_down(Event(self, EventTypes.MFRT, ack)) self.send_parent_req() elif not self.is_waiting: self.send_self( Event(self, FireWirePacketType.ROOT_CONTENTION, "...")) else: print( f" 👑 {self.componentinstancenumber} is elected as the leader" ) self.is_leader = True self.is_terminated = True elif (header.messagetype == FireWirePacketType.ACKNOWLEDGEMENT and header.messagefrom == self.parent): # This node's parent request got acknowledged, the process can # safely terminate print(f"🤖 {self.componentinstancenumber} received an ACK " f" from {header.messagefrom}, terminating") self.is_terminated = True self.in_root_contention = False self.callback.set() self.draw_delay.wait() self.draw_delay.clear()
def start_traverse(self): token = self.create_token() self.send_self( Event( self, EventTypes.MFRB, self.prepare_message(DfsMessageTypes.START, self.componentinstancenumber, token, [])))
def send_parent_req(self): """Send a parent request to the only eligible neighbour node. The neighbour node should not have sent this node a parent request and the number of such neighbours of this node should be 1. """ # if there is *only* one possible parent then send them a parent request here result = self.neighbours - set(self.received) if len(result) == 1: par = result.pop() self.parent = par print( f"🤖 {self.componentinstancenumber} picked {self.parent} as it's parent" ) next_hop_interface_id = f"{self.componentinstancenumber}-{self.parent}" header = FireWireMessageHeader( messagefrom=self.componentinstancenumber, messageto=self.parent, nexthop=self.parent, messagetype=FireWirePacketType.PARENT_REQ, interfaceid=next_hop_interface_id, ) payload = FireWireMessagePayload() message = GenericMessage(header, payload) self.send_down(Event(self, EventTypes.MFRT, message)) else: # Cannot send a parent request, more than one possible parent return
def send_random_basic_message(self, to: int) -> None: self.send_down( Event( self, EventTypes.MFRT, self.prepare_application_layer_message( ApplicationLayerMessageType.BASIC, to, str(dt.now().timestamp()))))
def call_wave(self): print(f" > CALL WAVE @@ N-{self.componentinstancenumber}") to_nodes = [i for i in range(len(self.context["network"].G.nodes())) if i != self.componentinstancenumber] for to in to_nodes: self.send_down(Event(self, EventTypes.MFRT, self.prepare_application_layer_message(ApplicationLayerMessageType.WAVE, to, SFWaveMessagePayload(self.componentinstancenumber, SFWaveMessageType.REQUEST)))) self._wms += 1
def on_propose(self, eventobj: Event): destination = 1 hdr = ApplicationLayerMessageHeader( ApplicationLayerMessageTypes.ACCEPT, self.componentinstancenumber, destination) payload = ApplicationLayerMessagePayload("23") proposalmessage = GenericMessage(hdr, payload) self.send_down(Event(self, EventTypes.MFRT, proposalmessage))
def send_ack_control_message(self, to: int, is_dead: bool) -> None: # print(f"send_ack_control_message: N-{self.componentinstancenumber} ==> N-{to} ({self._parent_node}) : {'DEAD' if is_dead else 'PKG_RESP'}") self.send_down( Event( self, EventTypes.MFRT, self.prepare_application_layer_message( ApplicationLayerMessageType.CONTROL, to, str(dt.now().timestamp())))) self._cms += 1
def send_reply(self, nodeID): self.sentReplyCount += 1 nextHop = Topology().get_next_hop(self.componentinstancenumber, nodeID) interfaceID = f"{self.componentinstancenumber}-{nextHop}" header = RicartAgrawalaMessageHeader(RicartAgrawalaMessageTypes.REPLY, self.componentinstancenumber, nodeID, nextHop, interfaceID) payload = GenericMessagePayload(self.componentinstancenumber) message = GenericMessage(header, payload) self.send_down(Event(self, EventTypes.MFRT, message))
def on_message_from_bottom(self, eventobj: Event): msg = eventobj.eventcontent hdr = msg.header payload = msg.payload if hdr.messageto == self.componentinstancenumber or hdr.messageto == MessageDestinationIdentifiers.NETWORKLAYERBROADCAST: # Add if broadcast.... self.send_up(Event(self, EventTypes.MFRB, payload)) print(f"I received a message to {hdr.messageto} and I am {self.componentinstancenumber}") else: destination = hdr.messageto nexthop = Topology().get_next_hop(self.componentinstancenumber, destination) if nexthop != float('inf'): newhdr = NetworkLayerMessageHeader(NetworkLayerMessageTypes.NETMSG, self.componentinstancenumber, destination, nexthop) newpayload = eventobj.eventcontent.payload msg = GenericMessage(newhdr, newpayload) self.send_down(Event(self, EventTypes.MFRT, msg)) print(f"{self.componentinstancenumber} will FORWARD a message to {destination} over {nexthop}") else: print(f"NO PATH {self.componentinstancenumber} will NOT FORWARD a message to {destination} over {nexthop}")
def on_message_from_top(self, eventobj: Event): # if channelid != hdr.interfaceif then drop (should not be on this channel) hdr = eventobj.eventcontent.header if hdr.nexthop != MessageDestinationIdentifiers.LINKLAYERBROADCAST: if set(hdr.interfaceid.split("-")) == set(self.componentinstancenumber.split("-")): #print(f"Will forward message since {hdr.interfaceid} and {self.componentinstancenumber}") myevent = Event(eventobj.eventsource, ChannelEventTypes.INCH, eventobj.eventcontent) self.channelqueue.put_nowait(myevent) else: #print(f"Will drop message since {hdr.interfaceid} and {self.componentinstancenumber}") pass
def reply_received(self, eventobj: Event): self.receivedReplyCount += 1 replyFrom = eventobj.eventcontent.payload.messagepayload self.receivedReplies.add(replyFrom) if len(self.receivedReplies) == len(self.otherNodeIDs): self.send_self( Event(self, RicartAgrawalaEventTypes.PRIVILEGE, None)) elif len(self.receivedReplies) > len(self.otherNodeIDs): raise RuntimeError( "Received reply message count exceeded expected limit!")
def on_message_from_bottom(self, eventobj: Event): msg = eventobj.eventcontent hdr = msg.header payload = msg.payload if hdr.messageto == self.componentinstancenumber or hdr.messageto == MessageDestinationIdentifiers.LINKLAYERBROADCAST: self.send_up( Event(self, EventTypes.MFRB, payload, eventobj.fromchannel) ) # doing decapsulation by just sending the payload else: # print(f"I am {self.componentinstancenumber} and dropping the {hdr.messagetype} message to {hdr.messageto}") # Physical layer is a broadcast medium, and hence will accept all messages. The link layer will drop those messages that are not for me pass
def on_deliver_to_component(self, eventobj: Event): callername = eventobj.eventsource.componentinstancenumber for item in self.connectors: callees = self.connectors[item] for callee in callees: calleename = callee.componentinstancenumber # print(f"I am connected to {calleename}. Will check if I have to distribute it to {item}") if calleename == callername: pass else: myevent = Event(eventobj.eventsource, EventTypes.MFRB, eventobj.eventcontent, self.componentinstancenumber) callee.trigger_event(myevent)
def on_message_from_bottom(self, eventobj: Event): message = eventobj.eventcontent header = message.header messageType = header.messagetype messageTo = header.messageto if messageTo == self.componentinstancenumber: if messageType == RicartAgrawalaMessageTypes.REQUEST: eventobj.event = RicartAgrawalaEventTypes.REQUEST self.send_self(eventobj) elif messageType == RicartAgrawalaMessageTypes.REPLY: eventobj.event = RicartAgrawalaEventTypes.REPLY self.send_self(eventobj) else: nextHop = Topology().get_next_hop(self.componentinstancenumber, messageTo) interfaceID = f"{self.componentinstancenumber}-{nextHop}" if nextHop != inf and nextHop != self.componentinstancenumber: self.forwardedMessageCount += 1 header.nexthop = nextHop header.interfaceid = interfaceID self.send_down(Event(self, EventTypes.MFRT, message))
def senddownbroadcast(self, eventobj: Event, whosends, sequencenumber): applmsg = eventobj.eventcontent destination = MessageDestinationIdentifiers.NETWORKLAYERBROADCAST nexthop = MessageDestinationIdentifiers.LINKLAYERBROADCAST print( f"{self.componentinstancenumber} will SEND a message to {destination} over {nexthop}" ) hdr = BroadcastingMessageHeader(BroadcastingMessageTypes.SIMPLEFLOOD, whosends, destination, nexthop, sequencenumber) payload = applmsg broadcastmessage = GenericMessage(hdr, payload) self.send_down(Event(self, EventTypes.MFRT, broadcastmessage)) self.broadcastdb.append(broadcastmessage.uniqueid)
def on_message_from_top(self, eventobj: Event): # Encapsulate the SDU in network layer PDU applmsg = eventobj.eventcontent destination = applmsg.header.messageto nexthop = Topology().get_next_hop(self.componentinstancenumber, destination) if nexthop != float('inf'): print(f"{self.componentinstancenumber} will SEND a message to {destination} over {nexthop}") hdr = NetworkLayerMessageHeader(NetworkLayerMessageTypes.NETMSG, self.componentinstancenumber, destination, nexthop) payload = eventobj.eventcontent msg = GenericMessage(hdr, payload) self.send_down(Event(self, EventTypes.MFRT, msg)) else: print(f"NO PATH: {self.componentinstancenumber} will NOTSEND a message to {destination} over {nexthop}")
def on_message_from_bottom(self, eventobj: Event): msg = eventobj.eventcontent hdr = msg.header message_source = hdr.messagefrom payload: List[Any] = msg.payload.messagepayload if hdr.messagetype == WaveMessageTypes.FORWARD or hdr.messagetype == WaveMessageTypes.START: token = hdr.token if hdr.messagetype == WaveMessageTypes.START: self.token_parent_mapping[token] = -1 parent_for_token = self.token_parent_mapping.get(token, None) if parent_for_token == None: self.token_parent_mapping[token] = message_source parent_for_token = message_source message = None next_target = None """ Tarry's algorithm has 2 rules. 1 - A process never forwards the token through the same channel twice. 2 - A process only forwards the token to its parent when there is no other option. """ uninvoked_neighbors = [ n for n in self.get_neighbor_mapping_for_token(token) if n.invoked == False and n.id != parent_for_token ] if len(uninvoked_neighbors ) > 0: # If true, send to the available neighbor neigh = choice(uninvoked_neighbors) # neigh = uninvoked_neighbors[0] neigh.invoked = True next_target = neigh.id else: # Else, send the token back to the parent if parent_for_token == -1: # If I am the initiator, traversing is completed print("->".join(payload)) print("TRAVERSING IS COMPLETED IN " + str(len(payload)) + " hops") print(f"Graph had {Topology().G.number_of_edges()} edges") print(len(set(payload))) return else: next_target = parent_for_token payload.append(str(self.componentinstancenumber)) message = self.prepare_message(WaveMessageTypes.FORWARD, next_target, token, payload) self.send_down(Event(self, EventTypes.MFRT, message))
def send_request(self): self.sentRequestCount += 1 self.havePendingRequest = True self.pendingRequestClock = self.clock for nodeID in self.otherNodeIDs: nextHop = Topology().get_next_hop(self.componentinstancenumber, nodeID) interfaceID = f"{self.componentinstancenumber}-{nextHop}" header = RicartAgrawalaMessageHeader( RicartAgrawalaMessageTypes.REQUEST, self.componentinstancenumber, nodeID, nextHop, interfaceID) payload = RicartAgrawalaMessagePayload( self.pendingRequestClock, self.componentinstancenumber) message = GenericMessage(header, payload) self.send_down(Event(self, EventTypes.MFRT, message))
def on_message_from_bottom(self, eventobj: Event): msg = eventobj.eventcontent hdr = msg.header payload = msg.payload if hdr.messagetype == BroadcastingMessageTypes.SIMPLEFLOOD: if hdr.messageto == self.componentinstancenumber or hdr.messageto == MessageDestinationIdentifiers.NETWORKLAYERBROADCAST: # Add if broadcast.... if msg.uniqueid in self.broadcastdb: pass # we have already handled this flooded message else: # Send to higher layers self.update_topology() self.send_up(Event(self, EventTypes.MFRB, payload)) # Also continue flooding once time.sleep(random.randint(1, 3)) self.senddownbroadcast( eventobj, eventobj.eventcontent.header.messagefrom, eventobj.eventcontent.header.sequencenumber)
def root_contention(self, eventobj: Event): if self.is_leader: return print(f"🤖 {self.componentinstancenumber} is in ROOT CONTENTION") decision = random.choice([True, False]) if decision: print(f"🤖 {self.componentinstancenumber} decides to YIELD") self.in_root_contention = True self.send_parent_req() self.is_waiting = False self.waiting_since = None else: print(f"🤖 {self.componentinstancenumber} decides to HOLD") self.is_waiting = True self.in_root_contention = False self.send_self(Event(self, FireWirePacketType.START_TIMER, "..."))
def on_init(self, eventobj: Event): print( f"Initializing {self.componentname}.{self.componentinstancenumber}" ) if self.componentinstancenumber == 0: # destination = random.randint(len(Topology.G.nodes)) destination = 1 hdr = ApplicationLayerMessageHeader( ApplicationLayerMessageTypes.PROPOSE, self.componentinstancenumber, destination) payload = ApplicationLayerMessagePayload("23") proposalmessage = GenericMessage(hdr, payload) randdelay = random.randint(0, 5) time.sleep(randdelay) self.send_self(Event(self, "propose", proposalmessage)) else: pass
def on_message_from_top(self, eventobj: Event): abovehdr = eventobj.eventcontent.header if abovehdr.messageto == MessageDestinationIdentifiers.NETWORKLAYERBROADCAST: hdr = LinkLayerMessageHeader( LinkLayerMessageTypes.LINKMSG, self.componentinstancenumber, MessageDestinationIdentifiers.LINKLAYERBROADCAST, nexthop=MessageDestinationIdentifiers.LINKLAYERBROADCAST) else: #if we do not broadcast, use nexthop to determine interfaceid and set hdr.interfaceid myinterfaceid = str(self.componentinstancenumber) + "-" + str( abovehdr.nexthop) hdr = LinkLayerMessageHeader(LinkLayerMessageTypes.LINKMSG, self.componentinstancenumber, abovehdr.nexthop, nexthop=abovehdr.nexthop, interfaceid=myinterfaceid) payload = eventobj.eventcontent msg = GenericMessage(hdr, payload) self.send_down(Event(self, EventTypes.MFRT, msg))
def on_message_from_bottom(self, eventobj: Event): self.send_up(Event(self, EventTypes.MFRB, eventobj.eventcontent))
def on_message_from_top(self, eventobj: Event): self.send_down(Event(self, EventTypes.MFRT, eventobj.eventcontent))
def on_init(self, eventobj: Event): evt = Event(self, EventTypes.MFRT, "A to lower layer") self.send_down(evt)
def on_message_from_top(self, eventobj: Event): print(f"I am {self.componentname}, eventcontent={eventobj.eventcontent}") evt = Event(self, EventTypes.MFRB, "L to higher layer") self.send_up(evt)
def on_message_from_top(self, eventobj: Event): print(f"I am {self.componentname}, eventcontent={eventobj.eventcontent}\n") evt = Event(self, EventTypes.MFRT, "N to lower layer") self.send_down(evt)