1 module libsweatyballs.engine.handlers; 2 3 import libsweatyballs.link.unit; 4 import libsweatyballs.link.message.core; 5 import libsweatyballs.engine.core; 6 import gogga; 7 import google.protobuf; 8 import std.string : cmp; 9 import std.conv : to; 10 import libsweatyballs.router.table : Route; 11 import std.socket : Address; 12 import libsweatyballs.zwitch.neighbor : Neighbor; 13 import libsweatyballs.link.core : Link; 14 import std.datetime : SysTime; 15 16 public __gshared Engine engine; 17 18 public void advHandler(LinkUnit unit) 19 { 20 /** 21 * Message details 22 * 23 * 1. Public key of Link Neighbor 24 * 2. Signature of Link Neighbor 25 * 3. Neighbor port of LinkNeighbor 26 * 4. Message type (also from LinkUnit address) 27 * 5. Payload 28 */ 29 link.LinkMessage message = unit.getMessage(); 30 link.LinkMessageType mType = message.type; 31 Address sender = unit.getSender(); 32 string identity = message.publicKey; 33 ushort neighborPort = to!(ushort)(message.neighborPort); 34 ubyte[] msgPayload = message.payload; 35 36 37 Address neighborAddress = Link.getNeighborIPAddress(sender, neighborPort); 38 Neighbor neighbor = new Neighbor(identity, neighborAddress, unit.getLink()); 39 40 Advertisement advMsg = fromProtobuf!(link.Advertisement)(msgPayload); 41 42 /* Get the routes being advertised */ 43 RouteEntry[] routes = advMsg.routes; 44 45 /* TODO: Do router2router verification here */ 46 47 /* Add each route to the routing table */ 48 foreach(RouteEntry route; routes) 49 { 50 uint metric = route.metric; 51 SysTime routeCreationTime = SysTime.fromISOString(route.creationTime); 52 53 /** 54 * Create a new route with `nexthop` as the nexthop address 55 * Also set its metric to whatever it is +64 56 */ 57 Route newRoute = new Route(route.address, neighbor, routeCreationTime, 100, metric+64); 58 59 engine.getRouter().getTable().lockTable(); 60 61 /** 62 * TODO: Found it, only install routes if their updated metric on arrival is lesser than current route 63 * TODO: Search for existing route 64 * TODO: This might make above constraints nmeaningless, or well atleast the one above me (outer one not me thinks) 65 */ 66 Route possibleExistingRoute = engine.getRouter().getTable().lookup(route.address); 67 68 /* If no route exists then add it */ 69 if(!possibleExistingRoute) 70 { 71 engine.getRouter().getTable().addRoute(newRoute); 72 } 73 /* If a route exists only install it if current one has higher metric than advertised one */ 74 else 75 { 76 /** 77 * If the route is already installed then simply update the creationTime field 78 */ 79 if(possibleExistingRoute == newRoute) 80 { 81 /* TODO: Even more reason to lock the table */ 82 possibleExistingRoute.updateCreationTime(routeCreationTime); 83 } 84 /** 85 * If the routes are not the same then go and check the metric to see if it is better 86 * and only install it if so 87 * 88 * TODO: Lock WHOLE table when doing these things (the below code is not logically safe) 89 */ 90 else if(possibleExistingRoute.getMetric() > newRoute.getMetric()) 91 { 92 /* Remove the old one (higher metric than advertised route) */ 93 engine.getRouter().getTable().removeRoute(possibleExistingRoute); 94 95 /* Install the advertised route (lower metric than currently installed route) */ 96 engine.getRouter().getTable().addRoute(newRoute); 97 } 98 else 99 { 100 /* TODO: Nothing needs to be done here */ 101 } 102 } 103 104 engine.getRouter().getTable().unlockTable(); 105 } 106 } 107 108 public void pktHandler(LinkUnit unit) 109 { 110 /** 111 * Message details 112 * 113 * 1. Public key of Link Neighbor 114 * 2. Signature of Link Neighbor 115 * 3. Neighbor port of LinkNeighbor 116 * 4. Message type (also from LinkUnit address) 117 * 5. Payload 118 */ 119 link.LinkMessage message = unit.getMessage(); 120 link.LinkMessageType mType = message.type; 121 Address sender = unit.getSender(); 122 string identity = message.publicKey; 123 ushort neighborPort = to!(ushort)(message.neighborPort); 124 ubyte[] msgPayload = message.payload; 125 126 127 Address neighborAddress = Link.getNeighborIPAddress(sender, neighborPort); 128 Neighbor neighbor = new Neighbor(identity, neighborAddress, unit.getLink()); 129 130 gprintln("pktHandler!!!!!!!!!! "~unit.toString()); 131 132 133 gprintln("Woohoo! PACKET received!", DebugType.WARNING); 134 135 try 136 { 137 138 /* TODO: Now check if destined to me, if so THEN attempt decrypt */ 139 link.Packet packet = fromProtobuf!(link.Packet)(msgPayload); 140 gprintln("Payload (encrypted): "~to!(string)(packet.payload)); 141 142 /* Attempt decrypting with my key */ 143 import crypto.rsa; 144 import std.string : cmp; 145 146 /* TODO: Make sure decryotion passes, maybe add a PayloadBytes thing to use that */ 147 ubyte[] decryptedPayload = RSA.decrypt(engine.getRouter().getIdentity().getKeys().privateKey, packet.payload); 148 gprintln("Payload (decrypted): "~cast(string)(decryptedPayload)); 149 150 /* Now see if it is destined to us */ 151 152 /* If it is destined to us (TODO: Accept it) */ 153 if(cmp(packet.toKey, engine.getRouter().getIdentity().getKeys().publicKey) == 0) 154 { 155 gprintln("PACKET IS ACCEPTED TO ME", DebugType.WARNING); 156 157 bool stat = engine.getSwitch().isNeighbour(packet.fromKey) !is null; 158 gprintln("WasPacketFromNeighbor: "~to!(string)(stat), DebugType.WARNING); 159 160 /* Deliver this to the engine */ 161 engine.newPacket(packet); 162 } 163 /* If it is not destined to me then forward it */ 164 else 165 { 166 engine.getSwitch().forward(packet); 167 gprintln("PACKET IS FORWRDED", DebugType.WARNING); 168 } 169 170 } 171 catch(ProtobufException) 172 { 173 gprintln("Failed to deserialize protobuff bytes", DebugType.ERROR); 174 } 175 } 176 177 public void defaultHandler(LinkUnit unit) 178 { 179 gprintln("Unknown mesage type!!!!!!!!!! "~unit.toString()); 180 }