import stackless class Nachricht:pass # node actions class Sende_Ping(Nachricht): def __init__(self, source, dest): self.source = source self.dest = dest class Packet(Nachricht): def __init__(self, source, dest, data): self.source = source self.dest = dest self.data = data self.hop = None def __str__(self): return '| %s | %s | %s' % (self.source,self.dest,self.data) def clone(self): msg = self.__class__(self.source, self.dest, self.data) msg.hop = self.hop return msg class Ping(Packet):pass class Actor: def __init__(self, name, in_channel): self.name = name self.in_channel = in_channel stackless.tasklet(self.taskloop)() def taskloop(self): while True: msg = self.in_channel.receive() self.action(msg) def action(self, msg): pass class HUB(Actor): def __init__(self, name, in_channel): Actor.__init__(self, name, in_channel) self.connectors = [] self.messages = [] def action(self, msg): # dispatch incoming packet to all connected devices self.messages.append(msg) while self.messages: msg = self.messages.pop() conn = self.connectors[:] while conn: out = conn.pop() if out.balance < 0: # is somebody waiting for reading? out.send(msg) else: conn.insert(0,out) if self.in_channel.balance > 0: self.messages.append(self.in_channel.receive()) # now we need to give everybody else the # chance to do what they have to do stackless.schedule() class Node(Actor): def __init__(self, name, in_channel): Actor.__init__(self, name, in_channel) self.interface = {} self.route = [] self.default_route = None self.name = name def action(self, msg): out_queue = [] if isinstance(msg, Packet): msg = msg.clone() if msg.hop is self: pass else: if isinstance(msg, Ping) and \ msg.dest in self.interface.keys(): if msg.data == 'TO': packet = Ping(msg.dest, msg.source,'BACK') out_queue.append(packet) else: print self.name,": Ping answer from", msg.source else: # route the packet out_queue.append(msg) elif isinstance(msg, Sende_Ping): print self.name,": Ping", msg.dest packet = Ping(msg.source, msg.dest, 'TO') out_queue.append(packet) # send packets for packet in out_queue: packet.hop = self lokales_routing = False # do I know the destination network? for adresse, (maske, kanal) in self.interface.items(): if packet.dest&maske == adresse&maske: lokales_routing = True kanal.send(packet) if not lokales_routing: for adresse, maske, ausgang in self.route: if packet.dest & maske == adresse: ausgang.send(packet) packet = None break; if packet is not None and self.default_route is not None: self.default_route.send(packet) def driver(): mask = 240 # binaer: 1111 0000 # the "computer" bach_channel = stackless.channel() bach = Node("bach", bach_channel) mozart_channel = stackless.channel() mozart = Node("mozart", mozart_channel) haydn_channel = stackless.channel() haydn = Node("haydn", haydn_channel) beethoven_channel = stackless.channel() beethoven = Node("beethoven", beethoven_channel) # the network HUBs net16_channel = stackless.channel() net16 = HUB('net16', net16_channel) net32_channel = stackless.channel() net32 = HUB('net32', net32_channel) net48_channel = stackless.channel() net48 = HUB('net48', net48_channel) # do the cabeling... net16.connectors.append(bach_channel) net16.connectors.append(mozart_channel) net32.connectors.append(mozart_channel) net32.connectors.append(haydn_channel) net48.connectors.append(haydn_channel) net48.connectors.append(beethoven_channel) # configure the computer interfaces bach.interface[18] = (mask, net16_channel) mozart.interface[17] = (mask, net16_channel) mozart.interface[33] = (mask, net32_channel) haydn.interface[34] = (mask, net32_channel) haydn.interface[49] = (mask, net48_channel) beethoven.interface[50] = (mask, net48_channel) # set the routes bach.default_route = net16_channel mozart.route.append((48, mask, net32_channel)) haydn.default_route = net32_channel beethoven.default_route = net48_channel # ping around bach_channel.send(Sende_Ping(18, 17)) beethoven_channel.send(Sende_Ping(50, 18)) bach_channel.send(Sende_Ping(18, 34)) bach_channel.send(Sende_Ping(18, 50)) if __name__ == '__main__': stackless.tasklet(driver)() stackless.run()