diff --git a/swarmsim/engine.nim b/swarmsim/engine.nim index 87939d0..0863f48 100644 --- a/swarmsim/engine.nim +++ b/swarmsim/engine.nim @@ -1,6 +1,7 @@ import engine/protocol import engine/network +import engine/message import engine/schedulableevent import timeutils -export protocol, network, schedulableevent, timeutils \ No newline at end of file +export protocol, network, schedulableevent, message, timeutils diff --git a/swarmsim/engine/message.nim b/swarmsim/engine/message.nim index 7881eec..3afd341 100644 --- a/swarmsim/engine/message.nim +++ b/swarmsim/engine/message.nim @@ -8,6 +8,8 @@ method `messageType`*(self: Message): string {.base.} = method `messageType`*(self: FreelyTypedMessage): string = self.messageType +proc allMessages*(self: type Message): string = "*" + func typeName(typeDef: NimNode): Option[NimNode] = expectKind typeDef, nnkTypeDef diff --git a/swarmsim/engine/peer.nim b/swarmsim/engine/peer.nim index 2892e86..3fbf45d 100644 --- a/swarmsim/engine/peer.nim +++ b/swarmsim/engine/peer.nim @@ -24,12 +24,22 @@ proc getProtocol*(self: Peer, id: string): Option[Protocol] = proc addProtocol*(self: Peer, protocol: Protocol): void = self.protocols[protocol.id] = protocol -proc deliver*(self: Peer, message: Message, engine: EventDrivenEngine, - network: Network): void = - self.dispatch.getOrDefault(message.messageType, @[]).apply( +proc deliverForType(self: Peer, messageType: string, message: Message, + engine: EventDrivenEngine, network: Network): void = + self.dispatch.getOrDefault(messageType, @[]).apply( proc (p: Protocol): void = p.deliver(message, engine, network)) -proc initPeer(self: Peer, protocols: seq[Protocol]): Peer = +proc deliver*(self: Peer, message: Message, engine: EventDrivenEngine, + network: Network): void = + self.deliverForType(message.messageType, message, engine, network) + self.deliverForType(Message.allMessages, message, engine, network) + +proc initPeer*(self: Peer, protocols: seq[Protocol], + peerId: Option[int] = none(int)): Peer = + + self.peerId = peerId.get(rand(high(int))) + self.protocols = initTable[string, Protocol]() + self.dispatch = MultiTable[string, Protocol].new() # XXX integer indexes or an enum would be better, but this is easier for protocol in protocols: let protocol = protocol # https://github.com/nim-lang/Nim/issues/16740 @@ -47,11 +57,4 @@ proc new*( protocols: seq[Protocol], peerId: Option[int] = none(int), ): Peer = - # XXX I can't have put this in the init proc as that would mean allowing public - # write access to every field in Peer. Not sure how to solve this in nim. - let peerId = peerId.get(rand(high(int))) - initPeer(Peer( - protocols: initTable[string, Protocol](), - peerId: peerId, - dispatch: MultiTable[string, Protocol].new() - ), protocols) + initPeer(Peer(), protocols, peerId) diff --git a/tests/engine/tpeer.nim b/tests/engine/tpeer.nim index 906cbc2..447c882 100644 --- a/tests/engine/tpeer.nim +++ b/tests/engine/tpeer.nim @@ -4,6 +4,7 @@ import std/sets import swarmsim/engine/eventdrivenengine import swarmsim/engine/network import swarmsim/engine/peer +import swarmsim/engine/message import ../helpers/inbox @@ -77,3 +78,19 @@ suite "peer": check(i1.messages == @[m1, m2]) + + test "should deliver all message types when listening to Message.allMessages": + let i1 = Inbox(id: "protocol1", messageTypes: @[Message.allMessages]) + + let peer = Peer.new(protocols = @[Protocol i1]) + + let m1: Message = FreelyTypedMessage(receiver: peer, messageType: "m1") + let m2: Message = FreelyTypedMessage(receiver: peer, messageType: "m2") + let m3: Message = FreelyTypedMessage(receiver: peer, messageType: "m3") + + peer.deliver(m1, engine, network) + peer.deliver(m2, engine, network) + peer.deliver(m3, engine, network) + + check(i1.messages == @[m1, m2, m3]) +