Forwarding and TTL

This commit is contained in:
Djeeberjr 2022-03-01 16:59:53 +01:00
parent d65b06a9b4
commit eb43c51e50
4 changed files with 75 additions and 33 deletions

View File

@ -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<Int, Callback<Package>> = new Map();
@ -48,6 +49,7 @@ class Net {
Called when a new package comes in.
**/
private function handle(pack:Package,interf: INetworkInterface) {
if (pack.toID == this.networkID || pack.toID == Net.BRODCAST_PORT){
switch pack.type {
case Data(_) | DataNoResponse(_):
// Let a local proccess handle it
@ -61,6 +63,10 @@ class Net {
// Delegate to Routing
Routing.instance.handleRoutePackage(pack,interf);
}
}else{
// New message received but its not ment for us. Forward if possible.
forwardPackage(pack);
}
}
private function generateMessageID():Int {
@ -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<Package> {
return new Promise<Package>((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;

View File

@ -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,
};
}

View File

@ -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};
}
var route = this.routingTable[networkID];
if (route == null){
return null;
}else{
return {interf: route.interf,rep: route.rep};
}
}
}

View File

@ -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);