updateFromNeighborAdvertisements method

DistanceVectorRoutingTable<T>? updateFromNeighborAdvertisements(
  1. DistanceVectorRoutingTable<T> currentTable,
  2. Map<T, NeighborAdvertisement<T>> advertisements,
  3. Map<T, Map<T, num>> network
)

Updates routing table based on neighbor advertisements

currentTable - Current routing table advertisements - New neighbor advertisements network - Current network topology

Returns updated routing table if changes occurred

Implementation

DistanceVectorRoutingTable<T>? updateFromNeighborAdvertisements(
  DistanceVectorRoutingTable<T> currentTable,
  Map<T, NeighborAdvertisement<T>> advertisements,
  Map<T, Map<T, num>> network,
) {
  bool hasChanges = false;
  final updatedNeighborAds = Map<T, NeighborAdvertisement<T>>.from(
    currentTable.neighborAdvertisements,
  );

  // Update neighbor advertisements
  for (final entry in advertisements.entries) {
    final neighbor = entry.key;
    final advertisement = entry.value;

    // Check if this is a new or updated advertisement
    if (!updatedNeighborAds.containsKey(neighbor) ||
        advertisement.sequenceNumber >
            updatedNeighborAds[neighbor]!.sequenceNumber) {
      updatedNeighborAds[neighbor] = advertisement;
      hasChanges = true;
    }
  }

  if (!hasChanges) return null;

  // Recompute routes with updated neighbor information
  final recomputed = computeRoutes(
    network,
    currentTable.sourceNode,
    initialAdvertisements: updatedNeighborAds,
  );

  // Merge advertised destinations into the routing table so that
  // newly learned advertisements (even from external/unknown neighbors)
  // show up as routes. This mirrors real DVR implementations where
  // advertised destinations are recorded even if not immediately
  // reachable via the current topology snapshot.
  final mergedRoutes = Map<T, DistanceVectorRouteEntry<T>>.from(
    recomputed.routes,
  );

  for (final ad in updatedNeighborAds.values) {
    for (final dest in ad.distanceVector.keys) {
      if (!mergedRoutes.containsKey(dest)) {
        mergedRoutes[dest] = DistanceVectorRouteEntry<T>(
          destination: dest,
          nextHop: ad.neighbor,
          cost: ad.distanceVector[dest]!,
          lastUpdate: DateTime.now(),
          isDirectlyConnected: false,
          advertisingNeighbor: ad.neighbor,
          hopCount: 1,
          attributes: {'timeout': routeTimeout},
        );
      }
    }
  }

  return DistanceVectorRoutingTable<T>(
    sourceNode: recomputed.sourceNode,
    routes: Map.unmodifiable(mergedRoutes),
    neighborAdvertisements: Map.unmodifiable(updatedNeighborAds),
    lastUpdate: recomputed.lastUpdate,
    totalRoutes: mergedRoutes.length,
    totalNeighbors: updatedNeighborAds.length,
  );
}