/************************************************************************************ * Copyright (C) 2008 by Politehnica University of Bucharest and Rutgers University * All rights reserved. * Refer to LICENSE for terms and conditions of use. ***********************************************************************************/ package vnsim.applications.vitp.routing; import java.util.*; import java.io.*; import vnsim.applications.trafficview.SimulatedCarInfo; import vnsim.applications.vitp.CarRunningVITP; import vnsim.applications.vitp.Statistics; import vnsim.applications.vitp.peer.Peer; import vnsim.applications.vitp.utils.*; import vnsim.core.CarInfo; import vnsim.core.Engine; import vnsim.map.object.*; import vnsim.map.utils.GPSutil; import vnsim.vehicular.simulator.CarInstance; import vnsim.vehicular.simulator.Location; import vnsim.vehicular.simulator.RouteSegment; import vnsim.vehicular.simulator.RoutingUtils; public class RoutingModule { java.util.Random random=new Random(System.currentTimeMillis()); MessageIndexModule mim; public CarRunningVITP car; Peer peer; public void attachModules(CarRunningVITP car, MessageIndexModule mim, Peer p){ this.car=car; this.mim=mim; this.peer=p; } public boolean postMessageFromAbove(VITPMessage msg) { //method to be called by the layer above, in order to send a message //to this routing module; returns true, if the message was properly //dealt with, false otherwise //the routing module has received a message from the peer; first, it //checks whether it has a valid id; if not, it provides a new one if(msg.isIdInval()) { msg.setMsgId(MessageIndexModule.getNewMessageIdentifier()); mim.addToPending(msg.getId()); //also set the correct source msg.source=getCurrentRouteSegment(); } //System.out.println("Has to route a message:"+msg); //build a RoutingPacket and route it //msg came from above; if it's destination is exactly the current location, then we //are during the computation phase or during the reply delivery phase; in either way, //the routing module should search for the closest neighbor, along the current segmentId Location myloc=new Location(car.getRoadIdx(), car.getPointIdx()); //check whether destination fits my current location //ONLY FOR SOME TESTING PURPOSES! SHOULD NOT BE HERE!!! // if(msg.isRequest()) { // VITPRequest req=(VITPRequest) msg; // if(req.isPost()){ // // if(!mim.wasBroadcasted(req.getId())) { // //broadcast it now and reschedule it // //periodically // //// System.out.println("OK : "+car.getVehicleId()); // // mim.addToBroacasted(req.getId()); // return broadcastPostMessage(req); // } else { //// System.out.println("ALREADY : "+car.getVehicleId()); // } // return true; // } // } // END !!!!!!!!!!!!!!!!!!!!!!!!!!! if(msg.getDest().contains(myloc)) { //is it a POST? Then broadcast it if(msg.isRequest()) { VITPRequest req=(VITPRequest) msg; if(req.isPost()){ if(!mim.wasBroadcasted(req.getId())) { //broadcast it now and reschedule it //periodically mim.addToBroacasted(req.getId()); return broadcastPostMessage(req); } else { // System.out.println("ID="+car.getVehicleId()+";WAS BROADCASTED!!!"); } return true; } } //fits //assume P1 -- C -- N -- P2, where P1,P2=end points of destination route segment, //C=current location ; N=candidate nodes; //look among N for the node farthest from P2 ArrayList neighbors=car.trafficDB; // System.out.println("I am at:"+myloc); // System.out.println("My neighbors:"+neighbors); double distance=0; int indice=-1; Integer sentTo=mim.sentTo(msg.getId()); for(int i=0;idistance) { distance=msg.getDest().distanceBetween(neig); indice=i; } } } catch (Exception ex) { continue; //try another neighbor } } if(distance!=0) { return unicastPacketToNeighbor( new RoutingPacket(msg, null), neighbors.get(indice) ); //unicast to neighbor 'indice' } else { if(msg.isReply()) { System.out.println("ROUTING MODULE: No node found during the reply delivery phase! Discarding!"); return false; } try{ if(((VITPRequest)msg).isPost()) return true; //a POST message is discarded, as there is no //other node to send it to. } catch (ClassCastException ex){ System.out.println("RoutingModule:ClassCastException:"+ex.toString()); return false; } System.out.println("ROUTING MODULE: No node found during the computation phase; Building the reply!"); //build reply RoutingPacket packet=buildReply(msg, myloc); try{ System.out.println("BEFORE!"); return standardRouting(packet); } catch(Exception ex){ System.out.println("RoutingModule.postMessageFromAbove()-EXCEPTION!"+ex.toString()); return false; } } } //the destination is not the current segment, so use standard routing, the VITP packet just //came from a peer module, thus the route should be calculated; // ArrayList route=RoutingUtils.getUnmergedDijkstraPath(msg.source, msg.dest); ArrayList route=RoutingUtils.getUnmergedDijkstraPath(myloc, new Location(msg.dest.roadIndex, msg.dest.pt1)); route.add(msg.dest); // System.out.println("ROUTING MODULE: I have calculated route for packet:"+msg); // System.out.println("THE ROUTE IS: "+route); RoutingPacket packet=new RoutingPacket(msg, route); try{ return standardRouting(packet); } catch (Exception ex){ System.out.println("RoutingModule.postMessageFromAbove()-EXCEPTION!"+ex.toString()); return false; } } private RoutingPacket buildReply(VITPMessage msg, Location myloc) { VITPReply repret=msg.getReversedVITP(); repret.setStatus("ERROR"); repret.source=new RouteSegment((short)myloc.roadIdx, (short)myloc.ptIdx, (short)myloc.ptIdx); System.out.println("ROUTING MODULE: calculating route for packet:"+repret); // ArrayList route=RoutingUtils.getUnmergedDijkstraPath(new RouteSegment((short)myloc.roadIdx, (short)myloc.ptIdx, (short)myloc.ptIdx), repret.dest); ArrayList route=RoutingUtils.getUnmergedDijkstraPath(myloc, new Location(repret.dest.roadIndex, repret.dest.pt1)); route.add(repret.dest); System.out.println("DONE CALCULATING ROUTE! ROUTE IS:"+route); RoutingPacket packet=new RoutingPacket(repret, route); return packet; } public boolean postMessageFromBelow(RoutingPacket packet) { //method to be called by the layer below, in order to send a message //to this routing module; returns true, if the message was properly //dealt with, false otherwise //the routing module has received a message from the layer below if(peer==null){ System.out.println("ERROR! Routing module not connected with a peer module!"); return false; } VITPMessage msg=packet.msg; Location myloc=new Location(car.getRoadIdx(), car.getPointIdx()); //System.out.println("ROUTING MODULE; location="+myloc+"; I have received a packet:"+packet); if(packet.getNextSegment()!=null) { if(packet.getNextSegment().contains(myloc)) packet.incrementIndex(); } //check if it's a reply for a pending request if(msg.isReply()) { if(mim.isPending(msg.getId())) { mim.removeFromPending(msg.getId()); return peer.postMessageFromBelow(msg); }; if(packet.toBroadcast) { //if I am in the broadcast zone and I did not //broadcast this message before, then broadcast it if(!mim.wasBroadcasted(msg.getId())) { Point p1=Globals.map.roads.get(myloc.roadIdx).points.get(myloc.ptIdx); Point p2=Globals.map.roads.get(packet.roadIndex).points.get(packet.pointIndex); double dist=GPSutil.distance(p1, p2); if(dist < packet.radius) { mim.addToBroacasted(msg.getId()); return broadcastPacket(packet); } else { //do not broadcast it further // System.out.println("DIST="+dist+"; RADIUS="+packet.radius); return true; } } return true; } //is it for the current location? if(msg.getDest().contains(myloc)) { //it's the first time the message has arrived in //the destination area; change it to a broadcast //message RoutingPacket newPacket=new RoutingPacket(msg, new ArrayList()); newPacket.toBroadcast=true; newPacket.roadIndex=msg.dest.roadIndex; newPacket.pointIndex=msg.dest.pt2; newPacket.radius=0.100; //100 meters mim.addToBroacasted(msg.getId()); return broadcastPacket(newPacket); } /* OLD METHOD : route the message from vehicle to vehicle //fits //assume P1 -- C -- N -- P2, where P1,P2=end points of destination route segment, //C=current location ; N=candidate nodes; //look among N for the node farthest from P2 ArrayList neighbors=car.neighbors; double distance=0.0; int indice=-1; for(int i=0;idistance) { distance=msg.getDest().distanceBetween(neig); indice=i; } } } if(indice!=-1) { return unicastPacketToNeighbor( new RoutingPacket(msg, null), neighbors.get(indice)); //unicast to neighbor 'indice' } else { //cannot route this reply! Discard it System.out.println("Discarding reply:"+msg); return false; } */ } //check if it's a request intended for the local peer if(msg.isRequest()) { if(msg.getDest().contains(myloc) ) { return peer.postMessageFromBelow(msg); } else { //is it a POST broadcasted from inside its destination area? //(and it got to me by chance) //then discard it! VITPRequest req=(VITPRequest) msg; if(req.isPost() && packet.toBroadcast) return true; } } //if not, then try to route the packet, based on the routing information in it, //find the appropriate neighbor in the neighbors list and //send the packet to it; try{ boolean ret=standardRouting(packet); if(!ret) { if(msg.isRequest()) { //build reply RoutingPacket pack=buildReply(msg, myloc); return standardRouting(pack); } else return false; } return true; } catch(Exception ex) { System.out.println("EXCEPTION-RoutingModule.postMessageFromBelow()"); return false; } } public boolean standardRouting(RoutingPacket packet) { //try to find the first node on the next segment (closest to the origin of the next //segment), or the farthest along the same segment (closest to the end of the current //segment); prefer next segment, if there is a node there; ArrayList neighbors=car.trafficDB; Location myloc=new Location(car.getRoadIdx(), car.getPointIdx()); // if(myloc==null) { // System.out.println("ROUTING MODULE: unknown current location - can't route!"); // return false; // } if(neighbors==null) { System.out.println("ROUTING MODULE: No neighbors! Can't route!"); return false; } double distance1 = Double.MAX_VALUE; int index1=-1; double distance2 = Double.MAX_VALUE; int index2=-1; // System.out.println("STANDARD ROUTING! I AM AT:"+car.getVehicleId()+"; POS="+car.getRoadIdx()+";"+car.getPointIdx()+ " SIZE="+car.neighbors.size()); for(int i=0;i Engine.WIRELESS_RANGE) { continue; } try { Location neighbor=new Location(neighbors.get(i).getRoadIdx(), neighbors.get(i).getPointIdx()); // System.out.println("CHECKING : "+neighbor); if(packet.getNextSegment()!=null && packet.getNextSegment().contains(neighbor)) { //that's on the next segment // System.out.println("IS ON NEXT SEG!"); if(packet.getNextSegment().distanceFrom(neighbor) < distance1 ) { index1=i; // System.out.println("IS BETTER!"); distance1=packet.getNextSegment().distanceFrom(neighbor); } } // System.out.println("B--Neighbor:"+i); if( (packet.getCurrentSegment()!=null && packet.getCurrentSegment().contains(neighbor) && packet.getCurrentSegment().checkOrder(myloc, neighbor) || (packet.getCurrentSegment()!=null && !packet.getCurrentSegment().contains(myloc)))) { //it's in the same segment; also it's further that myself // System.out.println("IS ON SAME SEG!"); if(packet.getCurrentSegment().distanceBetween(neighbor) < distance2 ) { index2=i; // System.out.println("IS BETTER!"); distance2=packet.getCurrentSegment().distanceBetween(neighbor); } } } catch (Exception ex) { continue; //try another neighbor } } System.out.flush(); if(index1!=-1) { //there was one node on the next segment // System.out.println("There was some node on the next segment:"+packet.getNextSegment()+"; ID="+neighbors.get(index1).getVehicleId()); // packet.incrementIndex(); return unicastPacketToNeighbor(packet, neighbors.get(index1)); } if(index2!=-1) { //there was one node on the current segment // System.out.println("There was nobody on the next segment:"+packet.getNextSegment()); return unicastPacketToNeighbor(packet, neighbors.get(index2)); } System.out.println("ROUTING MODULE AT "+car.getRoadIdx()+" ; "+car.getPointIdx()+" : no suitable neighbor found! Discarding packet!"); return false; } private RouteSegment getCurrentRouteSegment() { //used to set the correct source for a newly generated //VITP request int pt1, pt2; int road=car.getRoadIdx(); int point=car.getPointIdx(); Road r=Globals.map.roads.get(road); if(r.points.size() P) // return true; //probabilistic --> do not broadcast int delay= (int)( RAND2 * 2 * Globals.executionFPS ); int t=car.scheduleNewSendEvent(Globals.MESSAGE_PROCESSING_TIME+delay, 3000); //System.out.println("BROADCAST; T="+t); car.periodicalBroadcasts.put(t, req.dest); RoutingPacket packet=new RoutingPacket(req, null); packet.toBroadcast=true; ByteArrayOutputStream bos=new ByteArrayOutputStream(); try { ObjectOutputStream oos=new ObjectOutputStream(bos); oos.writeObject(packet); oos.flush(); car.messagesToSend.put(t, bos.toByteArray()); } catch (Exception ex) { System.out.println("EXCEPTION RoutingModule UNICAST TO NEIGHBOR:"+ex.toString()); ex.printStackTrace(); } return true; } private boolean broadcastPacket(RoutingPacket p) { Statistics.addBroadcast(p.msg.getId()); // System.out.println("BROADCASTING "+p); int t=car.scheduleSingleSendEvent(Globals.MESSAGE_PROCESSING_TIME, null); ByteArrayOutputStream bos=new ByteArrayOutputStream(); try { ObjectOutputStream oos=new ObjectOutputStream(bos); oos.writeObject(p); oos.flush(); car.messagesToSend.put(t, bos.toByteArray()); } catch (Exception ex) { System.out.println("EXCEPTION RoutingModule UNICAST TO NEIGHBOR:"+ex.toString()); ex.printStackTrace(); } return true; } private boolean unicastPacketToNeighbor(RoutingPacket p, CarInfo neighbor) { // System.out.println("UNICASTING "+p+" TO NEIGHBOR:"+neighbor); Statistics.addHop(p.msg.getId()); int delay = (int)(Globals.MESSAGE_PROCESSING_TIME + random.nextDouble()* 2 * Globals.executionFPS); int standardFPSPeriod = (int)((double)(SimulatedCarInfo.STANDARD_MESSAGE_PERIOD * Globals.engine.fps) / 1000); int t = car.scheduleNewSendEvent(delay, new Integer(standardFPSPeriod)); mim.addToSent(p.msg.getId(),neighbor.getVehicleId()); ByteArrayOutputStream bos=new ByteArrayOutputStream(); try { ObjectOutputStream oos=new ObjectOutputStream(bos); oos.writeObject(p); oos.flush(); car.messagesToSend.put(t, bos.toByteArray()); } catch (Exception ex) { System.out.println("EXCEPTION RoutingModule UNICAST TO NEIGHBOR:"+ex.toString()); ex.printStackTrace(); } return true; } public static double getRealDistance(int id1, int id2) { //id1, id2 = vehicle ids boolean found1=false, found2=false; synchronized(Globals.engine.cars) { Iterator iter=Globals.engine.cars.iterator(); int rd1=-1, rd2=-1, pt1=-1, pt2=-1; while(iter.hasNext()) { SimulatedCarInfo next=iter.next(); if(!found1 && next.getVehicleId()==id1) { rd1=next.getRoadIdx(); pt1=next.getPointIdx(); found1=true; } if(!found2 && next.getVehicleId()==id2) { rd2=next.getRoadIdx(); pt2=next.getPointIdx(); found2=true; } } if(!found1 || !found2) { System.out.println("ERROR! RoutingModule.getRealDistance() !"); return Double.MIN_VALUE; } Road r1=Globals.map.roads.get(rd1); Point p1=r1.points.get(pt1); Road r2=Globals.map.roads.get(rd2); Point p2=r2.points.get(pt2); return GPSutil.distance(p1, p2); } } }