diff --git a/src/kernel/net/Net.hx b/src/kernel/net/Net.hx index 79e800e..fecffc6 100644 --- a/src/kernel/net/Net.hx +++ b/src/kernel/net/Net.hx @@ -2,11 +2,11 @@ package kernel.net; using tink.CoreApi; +import kernel.net.Package.NetworkID; import kernel.peripherals.Peripherals.Peripheral; import kernel.Log; import kernel.KernelEvents; import haxe.Exception; -import util.Promise; import kernel.Timer; import cc.OS; @@ -22,14 +22,14 @@ class Net { public static inline final BRODCAST_PORT:Int = 65533; public static inline final MESSAGE_TIMEOUT:Int = 3; - public final onNewNeigbor: Signal; + public final onNewNeigbor:Signal; - private final networkID:Int = OS.getComputerID(); - private var responseBus:Map> = new Map(); - private var protoHandlers:Map> = new Map(); + public final networkID:NetworkID = OS.getComputerID(); + private final responseBus:Map> = new Map(); + private final protoHandlers:Map> = new Map(); private var allModems:Array; - private var routingTable:Map = new Map(); - private final onNewNeigborTrigger: SignalTrigger = Signal.trigger(); + private final routingTable:Map = new Map(); + private final onNewNeigborTrigger:SignalTrigger = Signal.trigger(); @:allow(kernel.Init) private function new() { @@ -52,24 +52,27 @@ class Net { discoverNeighbors(); } + /** + Called when a new package comes in. + **/ private function handelIncomming(pack:Package, ?addr:String) { switch pack.type { case Data(_): - routeTo(pack); + routeToProto(pack); case DataNoResponse(_): - routeTo(pack); - case Response | RouteDiscoverResponse: - if (responseBus.exists(pack.msgID)){ + routeToProto(pack); + case Response: + if (responseBus.exists(pack.msgID)) { responseBus[pack.msgID].invoke(pack); } - case RouteDiscover: - handleRoute(pack, addr); + case RouteDiscover(_) | RouteDiscoverResponse(_): + handleRouteDiscover(pack, addr); } } - private function newRoutPackage():Package { + private function newRoutDiscoverPackage():Package { var pack:Package = { - type: RouteDiscover, + type: RouteDiscover(getAllNeighbors()), toID: BRODCAST_PORT, msgID: generateMessageID(), fromID: networkID, @@ -79,33 +82,45 @@ class Net { return pack; } + /** + Send out discover packages on all modems. + **/ private function discoverNeighbors() { for (modem in allModems) { - var pack = newRoutPackage(); + var pack = newRoutDiscoverPackage(); - var timeout:Timer = null; - - responseBus[pack.msgID] = ((response:Package)->{ - addRoute(response.fromID, modem.addr); - }); - - timeout = new Timer(MESSAGE_TIMEOUT, () -> { - responseBus.remove(pack.msgID); - }); - - modem.transmit(BRODCAST_PORT, OS.getComputerID(), pack); + modem.transmit(BRODCAST_PORT, networkID, pack); } } - private function handleRoute(pack:Package, addr:String) { + /** + Handle incomming packages that involve route discovery. + **/ + private function handleRouteDiscover(pack:Package, addr:String) { addRoute(pack.fromID, addr); + var forward = getAllNeighbors().filter(i -> i == pack.fromID); + + switch pack.type{ + case RouteDiscoverResponse(reachableIDs): + for (id in reachableIDs) { + addRoute(id, addr); + } + return; // Dont respond to a response + case RouteDiscover(reachableIDs): + for (id in reachableIDs) { + addRoute(id, addr); + } + default: + throw new Error("Expcted RouteDiscover or RouteDiscoverResponse type"); + } + // Respond to peer var response:Package = { toID: pack.fromID, - fromID: OS.getComputerID(), + fromID: networkID, msgID: pack.msgID, - type: RouteDiscoverResponse, + type: RouteDiscoverResponse(forward), data: null } @@ -114,8 +129,12 @@ class Net { } } + /** + Called when a route to a client has been disoverd. + Its posible to be called multiple times with the same id but different addr. + **/ private function addRoute(toID:Int, addr:String) { - Log.debug("Added new route to " + toID + " via " + addr); + Log.info("Added new route to " + toID + " via " + addr); routingTable.set(toID, allModems.find(item -> item.addr == addr)); this.onNewNeigborTrigger.trigger(toID); } @@ -164,7 +183,10 @@ class Net { sendRaw(response); } - private function routeTo(pack:Package) { + /** + Send to package to the localy register handler based on the proto + **/ + private function routeToProto(pack:Package) { var proto:String = switch pack.type { case Data(proto): proto; @@ -181,6 +203,9 @@ class Net { protoHandlers[proto].invoke(pack); } + /** + Just send the package to the right modem. + **/ private function sendRaw(pack:Package) { if (pack.toID == networkID) { // Loopback @@ -195,7 +220,11 @@ class Net { } } - public function sendAndAwait(dest:Int, proto:String, data:Dynamic):Promise { + /** + 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, @@ -207,7 +236,7 @@ class Net { var timeout:Timer = null; - responseBus[pack.msgID] = ((reponse: Package) ->{ + responseBus[pack.msgID] = ((reponse:Package) -> { resolve(reponse); if (timeout != null) { timeout.cancle(); @@ -216,10 +245,13 @@ class Net { timeout = new Timer(MESSAGE_TIMEOUT, () -> { responseBus.remove(pack.msgID); - reject(new Exception("Timeout")); + reject(new Error(InternalError,"Message timeout")); }); sendRaw(pack); + + // No callback link for you + return null; }); } @@ -236,8 +268,4 @@ class Net { public function removeProto(proto:String) { protoHandlers.remove(proto); } - - public function getNeigbors():Array { - return this.routingTable.mapi((index, item) -> {return index;}); - } } diff --git a/src/kernel/net/Package.hx b/src/kernel/net/Package.hx index 6ba6a20..c16286f 100644 --- a/src/kernel/net/Package.hx +++ b/src/kernel/net/Package.hx @@ -1,19 +1,21 @@ package kernel.net; +typedef NetworkID = Int; + enum PackageTypes { Data(proto:String); DataNoResponse(proto:String); Response; - RouteDiscover(); - RouteDiscoverResponse(); + RouteDiscover(reachableIDs: Array); + RouteDiscoverResponse(reachableIDs: Array); } /** Representing a network package. **/ @:structInit class Package { - public final fromID:Int; - public final toID:Int; + public final fromID:NetworkID; + public final toID:NetworkID; public final msgID:Int; public final type:PackageTypes; public final data:Dynamic;