1 module libsweatyballs.router.table; 2 3 import std.socket : Address; 4 import core.sync.mutex : Mutex; 5 import std.conv : to; 6 import std.string : cmp; 7 import std.datetime.stopwatch : StopWatch; 8 import std.datetime : Duration; 9 import gogga; 10 import libsweatyballs.zwitch.neighbor; 11 12 /** 13 * Route 14 * 15 * Description: TODO 16 */ 17 public final class Route 18 { 19 // We must know our self-route and add it too somewhere 20 //private __gshared Identity d; 21 private string address; 22 private Neighbor nexthop; 23 private uint metric; 24 25 /** 26 * TODO: Set these and add a loop watcher to 27 * the table 28 */ 29 private long timeout; 30 private StopWatch updateTime; 31 32 private bool ageibility = true; 33 34 this(string address, Neighbor nexthop, long timeout = 100, uint metric = 64) 35 { 36 this.address = address; 37 this.nexthop = nexthop; 38 this.timeout = timeout; 39 this.metric = metric; 40 41 /* Start the stop watch */ 42 updateTime.start(); 43 } 44 45 public void refreshTime() 46 { 47 /* Reset the timer */ 48 updateTime.reset(); 49 } 50 51 public string getAddress() 52 { 53 return address; 54 } 55 56 public Neighbor getNexthop() 57 { 58 return nexthop; 59 } 60 61 public uint getMetric() 62 { 63 return metric; 64 } 65 66 public void setAgeibility(bool age) 67 { 68 ageibility = age; 69 } 70 71 public override string toString() 72 { 73 return "Route (To: "~address~", Via: "~to!(string)(nexthop)~", Metric: "~to!(string)(metric)~", Age: "~to!(string)(getAge())~")"; 74 } 75 76 public long getAge() 77 { 78 Duration elapsedTime = updateTime.peek(); 79 return elapsedTime.total!("seconds"); 80 } 81 82 public bool isExpired() 83 { 84 Duration elapsedTime = updateTime.peek(); 85 return (elapsedTime.total!("seconds") >= timeout) && ageibility; 86 } 87 88 public override bool opEquals(Object other) 89 { 90 Route otherRoute = cast(Route)other; 91 92 /* TODO: Add other comparators such as next hops */ 93 94 return cmp(otherRoute.getAddress(), this.getAddress()) == 0 && 95 otherRoute.getNexthop() == this.getNexthop() && 96 otherRoute.getMetric() == this.getMetric(); 97 } 98 } 99 100 /** 101 * Table 102 * 103 * Description: TODO 104 */ 105 public final class Table 106 { 107 /** 108 * Routes 109 */ 110 private Route[] routes; 111 private Mutex routeLock; 112 113 this() 114 { 115 /* Initialize locks */ 116 initMutexes(); 117 } 118 119 /** 120 * Initialize the mutexes 121 */ 122 private void initMutexes() 123 { 124 routeLock = new Mutex(); 125 } 126 127 /** 128 * Get routes 129 */ 130 public Route[] getRoutes() 131 { 132 /* The copied routes */ 133 Route[] copiedRoutes; 134 135 /* Lock the routing table */ 136 routeLock.lock(); 137 138 /* Copy each route */ 139 foreach(Route route; routes) 140 { 141 copiedRoutes ~= route; 142 } 143 144 /* Unlock the routing table */ 145 routeLock.unlock(); 146 147 return copiedRoutes; 148 } 149 150 /** 151 * Add a route 152 */ 153 public void addRoute(Route route) 154 { 155 /* Lock the routing table */ 156 routeLock.lock(); 157 158 /* Add the route (only if it doesn't already exist) */ 159 foreach(Route cRoute; routes) 160 { 161 /* FIXME: Make sure nexthop matches as well */ 162 if(cRoute == route) 163 { 164 /* Refresh the route */ 165 cRoute.refreshTime(); 166 167 goto no_add_route; 168 } 169 } 170 171 routes ~= route; 172 gprintln("Added route "~to!(string)(route)); 173 174 gprintln("TABLE IS HOW BIG MY NIGGER??!?!?: "~to!(string)(routes.length), DebugType.ERROR); 175 176 177 178 no_add_route: 179 180 /* Unlock the routing table */ 181 routeLock.unlock(); 182 } 183 184 public Route lookup(string address) 185 { 186 /* The matched route (if any) */ 187 Route match; 188 189 /* Lock the routing table */ 190 routeLock.lock(); 191 192 /* Add the route (only if it doesn't already exist) */ 193 foreach(Route route; routes) 194 { 195 /* FIXME: Make sure nexthop matches as well */ 196 if(cmp(route.getAddress(), address) == 0) 197 { 198 match = route; 199 } 200 } 201 202 /* Unlock the routing table */ 203 routeLock.unlock(); 204 205 return match; 206 } 207 208 /** 209 * Remove a route 210 */ 211 public void removeRoute(Route route) 212 { 213 /* New routing table */ 214 Route[] newRoutes; 215 216 /* Lock the routing table */ 217 routeLock.lock(); 218 219 /* Add the route (only if it doesn't already exist) */ 220 foreach(Route cRoute; routes) 221 { 222 /* FIXME: Make sure nexthop matches as well */ 223 if(cRoute != route) 224 { 225 newRoutes ~= cRoute; 226 } 227 } 228 229 routes = newRoutes; 230 231 /* Unlock the routing table */ 232 routeLock.unlock(); 233 } 234 }