diff --git a/src/kernel/net/Net.hx b/src/kernel/net/Net.hx index f38decf..1e2e72d 100644 --- a/src/kernel/net/Net.hx +++ b/src/kernel/net/Net.hx @@ -22,6 +22,7 @@ class Net { public static var instance:Net; public static inline final BRODCAST_PORT:Int = 65533; public static inline final MESSAGE_TIMEOUT:Int = 3; + public static inline final DEFAULT_TTL:Int = 10; public final networkID:NetworkID = OS.getComputerID(); private final responseBus:Map> = new Map(); @@ -48,18 +49,23 @@ class Net { Called when a new package comes in. **/ private function handle(pack:Package,interf: INetworkInterface) { - switch pack.type { - case Data(_) | DataNoResponse(_): - // Let a local proccess handle it - routeToProto(pack); - case Response: - // Got a response to a send message. Invoke the callback - if (responseBus.exists(pack.msgID)) { - responseBus[pack.msgID].invoke(pack); - } - case RouteDiscover(_) | RouteDiscoverResponse(_): - // Delegate to Routing - Routing.instance.handleRoutePackage(pack,interf); + if (pack.toID == this.networkID || pack.toID == Net.BRODCAST_PORT){ + switch pack.type { + case Data(_) | DataNoResponse(_): + // Let a local proccess handle it + routeToProto(pack); + case Response: + // Got a response to a send message. Invoke the callback + if (responseBus.exists(pack.msgID)) { + responseBus[pack.msgID].invoke(pack); + } + case RouteDiscover(_) | RouteDiscoverResponse(_): + // Delegate to Routing + Routing.instance.handleRoutePackage(pack,interf); + } + }else{ + // New message received but its not ment for us. Forward if possible. + forwardPackage(pack); } } @@ -76,12 +82,26 @@ class Net { fromID: networkID, msgID: generateMessageID(), type: DataNoResponse(proto), - data: data + data: data, + ttl: Net.DEFAULT_TTL, } sendRaw(pack); } + private function forwardPackage(pack: Package) { + if (pack.ttl == 0){ + // Drop package + return; + } + + pack.ttl--; + + if (sendRaw(pack)){ + // Cant forward + } + } + public function respondTo(pack:Package, data:Dynamic) { if (pack.type.match(DataNoResponse(_))) { Log.warn("Responed to a no response package. Ignoring"); @@ -97,16 +117,17 @@ class Net { Send to package to the localy register handler based on the proto **/ private function routeToProto(pack:Package) { - var proto:String = switch pack.type { + var proto = switch pack.type { case Data(proto): proto; case DataNoResponse(proto): proto; - case _: + default: return; } - if (!protoHandlers.exists(proto) && protoHandlers[proto] != null) { + if (!protoHandlers.exists(proto)) { + Log.warn("Trying to route package to proto: \"" + proto + "\" but nothing was register"); return; } @@ -115,24 +136,30 @@ class Net { /** Just send the package to the right modem. + Returns true if message was send **/ - private function sendRaw(pack:Package) { + private function sendRaw(pack:Package): Bool { + var route = Routing.instance.getRouteToID(pack.toID); + if (route == null){ + return false; + } - Routing.instance.getIterfaceToId(pack.toID).send(pack.toID,pack.fromID,pack); + route.interf.send(route.rep,this.networkID,pack); + return true; } /** Send a message and wait for a response. **/ public function sendAndAwait(dest:NetworkID, proto:String, data:Dynamic):Promise { - return new Promise((resolve, reject) -> { var pack:Package = { toID: dest, fromID: networkID, msgID: generateMessageID(), type: Data(proto), - data: data + data: data, + ttl: Net.DEFAULT_TTL, } var timeout:Timer = null; @@ -149,7 +176,9 @@ class Net { reject(new Error(InternalError,"Message timeout")); }); - sendRaw(pack); + if (!sendRaw(pack)){ + reject(new Error("ID unreachable")); + } // No callback link for you return null; diff --git a/src/kernel/net/Package.hx b/src/kernel/net/Package.hx index 7d9e569..25cba5e 100644 --- a/src/kernel/net/Package.hx +++ b/src/kernel/net/Package.hx @@ -19,6 +19,7 @@ enum PackageTypes { public final msgID:Int; public final type:PackageTypes; public final data:Dynamic; + public var ttl: Int; /** Parse package from an `modem_message` event. @@ -32,6 +33,7 @@ enum PackageTypes { msgID: payload.msgID, type: payload.type, data: payload.data, + ttl: payload.ttl, }; } @@ -44,7 +46,8 @@ enum PackageTypes { fromID: toID, msgID: msgID, type: Response, - data: newData + data: newData, + ttl: Net.DEFAULT_TTL, }; } diff --git a/src/kernel/net/Routing.hx b/src/kernel/net/Routing.hx index 6477fc5..660bcb3 100644 --- a/src/kernel/net/Routing.hx +++ b/src/kernel/net/Routing.hx @@ -9,6 +9,7 @@ import kernel.net.Package.NetworkID; @:structInit typedef Route = { interf:INetworkInterface, + rep: NetworkID, cost:Int } @@ -33,7 +34,7 @@ class Routing { @:allow(kernel.Init) private function init() { - routingTable.set(Net.instance.networkID,{interf: Loopback.instance,cost:0}); + routingTable.set(Net.instance.networkID,{interf: Loopback.instance,cost:0,rep:Net.instance.networkID}); for (modem in Peripheral.instance.getModems()) { modem.send(Net.BRODCAST_PORT, Net.instance.networkID, newRoutDiscoverPackage()); } @@ -43,17 +44,17 @@ class Routing { Handle incomming packages that involve route discovery. **/ public function handleRoutePackage(pack:Package, interf:INetworkInterface):Void { - addPossibleRoute(pack.fromID,interf,0); + addPossibleRoute(pack.fromID,interf,0,pack.fromID); var shouldRespond: Bool = switch pack.type { case RouteDiscoverResponse(routes): for (route in routes) { - addPossibleRoute(route.id,interf,route.cost); + addPossibleRoute(route.id,interf,route.cost,pack.fromID); } false; case RouteDiscover(routes): for (route in routes) { - addPossibleRoute(route.id,interf,route.cost); + addPossibleRoute(route.id,interf,route.cost,pack.fromID); } true; default: @@ -71,7 +72,8 @@ class Routing { fromID: Net.instance.networkID, msgID: null, type: RouteDiscoverResponse(genRouteList()), - data: null + data: null, + ttl: 0, // Prevent forwarding } interf.send(response.toID,Net.instance.networkID,response); @@ -95,6 +97,7 @@ class Routing { msgID: null, fromID: Net.instance.networkID, data: null, + ttl: 0, // Prevent forwarding } return pack; @@ -104,7 +107,7 @@ class Routing { Called when a route to a client has been disoverd. Its possible to be called multiple times with the same id but different addr. **/ - private function addPossibleRoute(toID:Int, interf:INetworkInterface, cost:Int) { + private function addPossibleRoute(toID:Int, interf:INetworkInterface, cost:Int, rep: NetworkID) { if (toID == Net.instance.networkID){ return; } @@ -114,20 +117,26 @@ class Routing { if (this.routingTable.exists(toID)){ if (this.routingTable[toID].cost > fullCost){ Log.info("Better route: " + toID + " -> " + interf.name() + ":$"+fullCost); - this.routingTable[toID] = {interf:interf,cost:cost + interf.getBaseRoutingCost()}; + this.routingTable[toID] = {interf:interf,cost:cost + interf.getBaseRoutingCost(),rep: rep}; } }else{ - this.routingTable[toID] = {interf:interf,cost:cost + interf.getBaseRoutingCost()}; + this.routingTable[toID] = {interf:interf,cost:cost + interf.getBaseRoutingCost(),rep: rep}; Log.info("New route: " + toID + " -> " + interf.name() + ":$"+fullCost); this.onNewNeigborTrigger.trigger(toID); } } - public function getIterfaceToId(networkID:NetworkID):INetworkInterface { + public function getRouteToID(networkID:NetworkID):{interf: INetworkInterface, rep: NetworkID} { if (networkID == Net.instance.networkID) { - return Loopback.instance; + return {interf: Loopback.instance,rep: Net.instance.networkID}; } - return null; + var route = this.routingTable[networkID]; + + if (route == null){ + return null; + }else{ + return {interf: route.interf,rep: route.rep}; + } } } diff --git a/src/kernel/peripherals/Modem.hx b/src/kernel/peripherals/Modem.hx index c367c2a..4b1be56 100644 --- a/src/kernel/peripherals/Modem.hx +++ b/src/kernel/peripherals/Modem.hx @@ -26,6 +26,7 @@ class Modem implements INetworkInterface implements IPeripheral { msgID: params.message.msgID, type: params.message.type, data: params.message.data, + ttl: params.message.ttl, }; this.onMessageTrigger.trigger(pack);