Compare commits

...

4 Commits

Author SHA1 Message Date
8318cc5c21 implemented distance vector routing 2022-03-01 17:28:15 +01:00
eb43c51e50 Forwarding and TTL 2022-03-01 16:59:53 +01:00
d65b06a9b4 updated README 2022-03-01 16:59:06 +01:00
66aa84d896 webconsole post improvement 2022-03-01 15:05:49 +01:00
6 changed files with 122 additions and 36 deletions

View File

@@ -24,6 +24,8 @@ run `make deps && make`. The `bundle.min.lua` inside the `build` dir is the fina
[CC wiki](https://tweaked.cc/) [CC wiki](https://tweaked.cc/)
[Tinkerbell Core Library](https://haxetink.github.io/tink_core/#/)
# Development # Development
There are a couple of tool to your disposal that makes working easier. There are a couple of tool to your disposal that makes working easier.

View File

@@ -22,6 +22,7 @@ class Net {
public static var instance:Net; public static var instance:Net;
public static inline final BRODCAST_PORT:Int = 65533; public static inline final BRODCAST_PORT:Int = 65533;
public static inline final MESSAGE_TIMEOUT:Int = 3; public static inline final MESSAGE_TIMEOUT:Int = 3;
public static inline final DEFAULT_TTL:Int = 10;
public final networkID:NetworkID = OS.getComputerID(); public final networkID:NetworkID = OS.getComputerID();
private final responseBus:Map<Int, Callback<Package>> = new Map(); private final responseBus:Map<Int, Callback<Package>> = new Map();
@@ -48,6 +49,7 @@ class Net {
Called when a new package comes in. Called when a new package comes in.
**/ **/
private function handle(pack:Package,interf: INetworkInterface) { private function handle(pack:Package,interf: INetworkInterface) {
if (pack.toID == this.networkID || pack.toID == Net.BRODCAST_PORT){
switch pack.type { switch pack.type {
case Data(_) | DataNoResponse(_): case Data(_) | DataNoResponse(_):
// Let a local proccess handle it // Let a local proccess handle it
@@ -57,10 +59,14 @@ class Net {
if (responseBus.exists(pack.msgID)) { if (responseBus.exists(pack.msgID)) {
responseBus[pack.msgID].invoke(pack); responseBus[pack.msgID].invoke(pack);
} }
case RouteDiscover(_) | RouteDiscoverResponse(_): case RouteDiscover(_) | RouteDiscoverResponse(_) | RouteDiscoverUpdate(_):
// Delegate to Routing // Delegate to Routing
Routing.instance.handleRoutePackage(pack,interf); Routing.instance.handleRoutePackage(pack,interf);
} }
}else{
// New message received but its not ment for us. Forward if possible.
forwardPackage(pack);
}
} }
private function generateMessageID():Int { private function generateMessageID():Int {
@@ -76,12 +82,26 @@ class Net {
fromID: networkID, fromID: networkID,
msgID: generateMessageID(), msgID: generateMessageID(),
type: DataNoResponse(proto), type: DataNoResponse(proto),
data: data data: data,
ttl: Net.DEFAULT_TTL,
} }
sendRaw(pack); 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) { public function respondTo(pack:Package, data:Dynamic) {
if (pack.type.match(DataNoResponse(_))) { if (pack.type.match(DataNoResponse(_))) {
Log.warn("Responed to a no response package. Ignoring"); 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 Send to package to the localy register handler based on the proto
**/ **/
private function routeToProto(pack:Package) { private function routeToProto(pack:Package) {
var proto:String = switch pack.type { var proto = switch pack.type {
case Data(proto): case Data(proto):
proto; proto;
case DataNoResponse(proto): case DataNoResponse(proto):
proto; proto;
case _: default:
return; 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; return;
} }
@@ -115,24 +136,30 @@ class Net {
/** /**
Just send the package to the right modem. 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. Send a message and wait for a response.
**/ **/
public function sendAndAwait(dest:NetworkID, proto:String, data:Dynamic):Promise<Package> { public function sendAndAwait(dest:NetworkID, proto:String, data:Dynamic):Promise<Package> {
return new Promise<Package>((resolve, reject) -> { return new Promise<Package>((resolve, reject) -> {
var pack:Package = { var pack:Package = {
toID: dest, toID: dest,
fromID: networkID, fromID: networkID,
msgID: generateMessageID(), msgID: generateMessageID(),
type: Data(proto), type: Data(proto),
data: data data: data,
ttl: Net.DEFAULT_TTL,
} }
var timeout:Timer = null; var timeout:Timer = null;
@@ -149,7 +176,9 @@ class Net {
reject(new Error(InternalError,"Message timeout")); reject(new Error(InternalError,"Message timeout"));
}); });
sendRaw(pack); if (!sendRaw(pack)){
reject(new Error("ID unreachable"));
}
// No callback link for you // No callback link for you
return null; return null;

View File

@@ -8,6 +8,7 @@ enum PackageTypes {
Response; Response;
RouteDiscover(reachableIDs: Array<{id:NetworkID,cost:Int}>); RouteDiscover(reachableIDs: Array<{id:NetworkID,cost:Int}>);
RouteDiscoverResponse(reachableIDs: Array<{id:NetworkID,cost:Int}>); RouteDiscoverResponse(reachableIDs: Array<{id:NetworkID,cost:Int}>);
RouteDiscoverUpdate(reachableIDs: Array<{id:NetworkID,cost:Int}>);
} }
/** /**
@@ -19,6 +20,7 @@ enum PackageTypes {
public final msgID:Int; public final msgID:Int;
public final type:PackageTypes; public final type:PackageTypes;
public final data:Dynamic; public final data:Dynamic;
public var ttl: Int;
/** /**
Parse package from an `modem_message` event. Parse package from an `modem_message` event.
@@ -32,6 +34,7 @@ enum PackageTypes {
msgID: payload.msgID, msgID: payload.msgID,
type: payload.type, type: payload.type,
data: payload.data, data: payload.data,
ttl: payload.ttl,
}; };
} }
@@ -44,7 +47,8 @@ enum PackageTypes {
fromID: toID, fromID: toID,
msgID: msgID, msgID: msgID,
type: Response, type: Response,
data: newData data: newData,
ttl: Net.DEFAULT_TTL,
}; };
} }

View File

@@ -9,6 +9,7 @@ import kernel.net.Package.NetworkID;
@:structInit typedef Route = { @:structInit typedef Route = {
interf:INetworkInterface, interf:INetworkInterface,
rep: NetworkID,
cost:Int cost:Int
} }
@@ -21,10 +22,13 @@ class Routing {
**/ **/
public static var instance:Routing; public static var instance:Routing;
public static inline final UPDATE_WAIT_TIME:Float = 3;
public final onNewNeigbor:Signal<Int>; public final onNewNeigbor:Signal<Int>;
private final onNewNeigborTrigger:SignalTrigger<NetworkID> = Signal.trigger(); private final onNewNeigborTrigger:SignalTrigger<NetworkID> = Signal.trigger();
private final routingTable:Map<NetworkID, Route> = new Map(); private final routingTable:Map<NetworkID, Route> = new Map();
private var routeUpdateInQueue: Bool = false;
@:allow(kernel.Init) @:allow(kernel.Init)
private function new() { private function new() {
@@ -33,29 +37,63 @@ class Routing {
@:allow(kernel.Init) @:allow(kernel.Init)
private function 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()) { for (modem in Peripheral.instance.getModems()) {
modem.send(Net.BRODCAST_PORT, Net.instance.networkID, newRoutDiscoverPackage()); modem.send(Net.BRODCAST_PORT, Net.instance.networkID, newRoutDiscoverPackage());
} }
} }
private function prepareRouteUpdate() {
if (this.routeUpdateInQueue){
return;
}
this.routeUpdateInQueue = true;
new Timer(UPDATE_WAIT_TIME,()->{
brodcastUpdatedRoutes();
this.routeUpdateInQueue = false;
});
}
private function brodcastUpdatedRoutes() {
var pack: Package = {
type: RouteDiscoverUpdate(genRouteList()),
toID: Net.BRODCAST_PORT,
msgID: null,
fromID: Net.instance.networkID,
data: null,
ttl: 0, // Prevent forwarding
};
for (modem in Peripheral.instance.getModems()) {
modem.send(Net.BRODCAST_PORT, Net.instance.networkID,pack);
}
}
/** /**
Handle incomming packages that involve route discovery. Handle incomming packages that involve route discovery.
**/ **/
public function handleRoutePackage(pack:Package, interf:INetworkInterface):Void { 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 { var shouldRespond: Bool = switch pack.type {
case RouteDiscoverResponse(routes): case RouteDiscoverResponse(routes):
for (route in routes) { for (route in routes) {
addPossibleRoute(route.id,interf,route.cost); addPossibleRoute(route.id,interf,route.cost,pack.fromID);
} }
false; false;
case RouteDiscover(routes): case RouteDiscover(routes):
for (route in routes) { for (route in routes) {
addPossibleRoute(route.id,interf,route.cost); addPossibleRoute(route.id,interf,route.cost,pack.fromID);
} }
true; true;
case RouteDiscoverUpdate(routes):
for (route in routes) {
addPossibleRoute(route.id,interf,route.cost,pack.fromID);
}
false;
default: default:
Log.error("Expected RouteDiscover or RouteDiscoverResponse type"); Log.error("Expected RouteDiscover or RouteDiscoverResponse type");
false; false;
@@ -71,7 +109,8 @@ class Routing {
fromID: Net.instance.networkID, fromID: Net.instance.networkID,
msgID: null, msgID: null,
type: RouteDiscoverResponse(genRouteList()), type: RouteDiscoverResponse(genRouteList()),
data: null data: null,
ttl: 0, // Prevent forwarding
} }
interf.send(response.toID,Net.instance.networkID,response); interf.send(response.toID,Net.instance.networkID,response);
@@ -95,6 +134,7 @@ class Routing {
msgID: null, msgID: null,
fromID: Net.instance.networkID, fromID: Net.instance.networkID,
data: null, data: null,
ttl: 0, // Prevent forwarding
} }
return pack; return pack;
@@ -104,7 +144,7 @@ class Routing {
Called when a route to a client has been disoverd. Called when a route to a client has been disoverd.
Its possible to be called multiple times with the same id but different addr. 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){ if (toID == Net.instance.networkID){
return; return;
} }
@@ -114,20 +154,28 @@ class Routing {
if (this.routingTable.exists(toID)){ if (this.routingTable.exists(toID)){
if (this.routingTable[toID].cost > fullCost){ if (this.routingTable[toID].cost > fullCost){
Log.info("Better route: " + toID + " -> " + interf.name() + ":$"+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};
this.prepareRouteUpdate();
} }
}else{ }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); Log.info("New route: " + toID + " -> " + interf.name() + ":$"+fullCost);
this.onNewNeigborTrigger.trigger(toID); this.onNewNeigborTrigger.trigger(toID);
this.prepareRouteUpdate();
} }
} }
public function getIterfaceToId(networkID:NetworkID):INetworkInterface { public function getRouteToID(networkID:NetworkID):{interf: INetworkInterface, rep: NetworkID} {
if (networkID == Net.instance.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; 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, msgID: params.message.msgID,
type: params.message.type, type: params.message.type,
data: params.message.data, data: params.message.data,
ttl: params.message.ttl,
}; };
this.onMessageTrigger.trigger(pack); this.onMessageTrigger.trigger(pack);

View File

@@ -1,9 +1,11 @@
package util; package util;
import cc.HTTP;
import kernel.net.Net;
import cc.ComputerCraft; import cc.ComputerCraft;
import kernel.Log; import kernel.Log;
#if webconsole
import cc.HTTP;
import kernel.net.Net;
#end
class Debug { class Debug {
public static function printBuildInfo() { public static function printBuildInfo() {
@@ -18,7 +20,7 @@ class Debug {
#if webconsole #if webconsole
public static function printWeb(msg:String) { public static function printWeb(msg:String) {
HTTP.post("http://127.0.0.1:8080/"+Net.instance.networkID, msg); HTTP.request("http://127.0.0.1:8080/"+Net.instance.networkID,msg);
} }
#end #end
} }