/** * @copyright 2013 Computer Science Department, Recursive InterNetworking Architecture (RINA) laboratory, Boston University. * All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation * for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all * copies and that both the copyright notice and this permission notice appear in supporting documentation. * The RINA laboratory of the Computer Science Department at Boston University makes no * representations about the suitability of this software for any purpose. */ package rina.ribDaemon.util; import java.util.LinkedHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import application.component.api.IPCResourceManager; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import rina.irm.impl.IRMImpl; import rina.message.CDAP; import rina.object.gpb.LinkStateRoutingEntrySet_t.routingEntrySetForwardedByNeighbor_t; import rina.object.gpb.LinkStateRoutingEntrySet_t.routingEntrySet_t; import rina.object.gpb.SubscriptionEvent_t.subscriptionEvent_t; import rina.object.internal.ForwardingTable; import rina.object.internal.LinkStateRoutingEntry; import rina.object.internal.Neighbor; import rina.object.internal.Neighbors; import rina.object.internal.SubscriptionEvent; import rina.object.internal.SubscriptionEvent.EventType; import rina.rib.impl.RIBImpl; import rina.routing.RoutingDaemon; import rina.routing.util.LinkStateRoutingInfo; /** * Event handler of subscription event * * @author Yuefeng Wang. Computer Science Department, Boston University * */ public class EventHandler{ private Log log = LogFactory.getLog(this.getClass()); private RIBImpl rib = null; private IPCResourceManager irm = null; private SubscriptionEvent event = null; private String attribute = null; // assume only one attribute for now private int rinaAddr; private String IPCName = null; private String IPCInstance = null; private ForwardingTable forwardingTable = null; private Neighbors neighbors = null; //for now we assume event's attribute list only contains one attribute // otherwise, here will be a list of publisher, since it might publish many things private Publisher publisher = null; private LinkStateRoutingInfo linkStateRoutingInfo = null; private RoutingDaemon routingDaemon = null; private String linkCostPolicy = null; //publisher's rina Addr private int publisherAddr; public EventHandler(RIBImpl rib,IPCResourceManager irm, SubscriptionEvent event) { this.rib = rib; this.irm = irm; this.rinaAddr = Integer.parseInt( this.rib.getAttribute("rinaAddr").toString() ); this.neighbors = (Neighbors)this.rib.getAttribute("neighbors"); this.forwardingTable = (ForwardingTable) this.rib.getAttribute("forwardingTable"); this.IPCName = (String) this.rib.getAttribute("ipcName"); this.IPCInstance = (String)this.rib.getAttribute("ipcInstance"); this.linkStateRoutingInfo = (LinkStateRoutingInfo) this.rib.getAttribute("linkStateRoutingInfo"); this.routingDaemon = (RoutingDaemon) this.rib.getAttribute("routingDaemon"); this.linkCostPolicy = (String) this.rib.getAttribute("linkCostPolicy"); this.event = event; this.attribute = this.event.getAtrributeList().get(0); this.handleEvent(); } public void handleEvent() { if(this.event.getEventType() == EventType.PUB) { this.publisher = new Publisher(this.rib,this.irm, this.event); //// if it is a PUB event, it needs to publish to its subscribers int num = this.event.getMemberList().size(); if( num>=1) { for(int i = 0; i < num; i++) { String subscriber = this.event.getMemberList().get(i);//only one member in the request event this.publisher.addSubsciber(subscriber); } } }else if(this.event.getEventType() == EventType.SUB) { this.sendSubRequest(); //send sub request M_START(Subscription Event) to publisher } } public void addSubscriber(String subscriber) { this.publisher.addSubsciber(subscriber); } private void sendSubRequest() { this.publisherAddr = Integer.parseInt(this.event.getMemberList().get(0)); // only sub to one publisher each time subscriptionEvent_t event_sub = this.event.getSendToPublisher(Integer.toString(this.rinaAddr) ); CDAP.objVal_t.Builder obj = CDAP.objVal_t.newBuilder(); obj.setByteval(ByteString.copyFrom(event_sub.toByteArray())); CDAP.CDAPMessage M_CREATE = rina.message.CDAPMessageGenerator.generateM_CREATE ( "subscription", "/daf/subscription", obj.buildPartial(), 99 ); int nextHop = this.forwardingTable.getNextHop(this.publisherAddr); this.log.debug("next hop of " + this.publisherAddr + " is " + nextHop); Neighbor neighbor = this.neighbors.getBeighbor(nextHop); if(neighbor == null) { this.log.info("Next hop does not exist for dstAddr " + this.publisherAddr ); return; } String dstIPCName = neighbor.getApName(); String dstIPCInstance = neighbor.getApInstance(); this.log.debug( "Next hop IPC info:" + dstIPCName + "/" + dstIPCInstance ); try { int handleID = this.irm.allocateFlow(this.IPCName, this.IPCInstance, "Management", "1", dstIPCName, dstIPCInstance, "Management", "1"); this.irm.send(handleID, M_CREATE.toByteArray()); this.log.info( "M_CREATE(subscription: sub) sent out over handleID " + handleID); } catch (Exception e) { this.log.error(e.getMessage()); System.err.println(e.getMessage()); return; } } public void updateSubEvent(byte[] value) { if(this.attribute.equals("linkStateRoutingEntry")) { // this.log.debug("linkStateRoutingEntry pub event received from " + this.publisherAddr); routingEntrySet_t routingEntrySet = null; try { routingEntrySet = routingEntrySet_t.parseFrom(value); } catch (InvalidProtocolBufferException e) { this.log.error(e.getMessage()); } long senderAddr = routingEntrySet.getAddr(); if( senderAddr == this.publisherAddr) //direct routingEntry, not a forwarded one { double cost = 0.0 ; //POLICY HOLDER : different ways to determine the link cost if(this.linkCostPolicy.equals("hop")) // hop count is the cost { cost = 1; }else if (this.linkCostPolicy.equals("myNewLinkCostPolicy")) { //implement new link cost policy here } else { // //this.log.info("Receive pub event(linkStateRoutingEntry) from " + this.publisherAddr + ", determine the cost to this neighbor"); // // long timeSent = routingEntrySet.getTimestamp(); // // long timeCurrent = System.currentTimeMillis(); // // //double cost = timeCurrent - timeSent; // // //manually set // // if(this.rinaAddr == 11 | senderAddr == 11 || this.rinaAddr == 14 || senderAddr == 14 ) // { // cost = 9; // } // else // { // cost = 10; // } } //this.log.debug("timeSent/timeCurrent/cost: " + timeSent + "/" + timeCurrent + "/" + cost ); this.linkStateRoutingInfo.addCostToNeighbor( (int)senderAddr, cost); if(routingEntrySet.getRoutingEntrySetCount() == 0 ) { this.log.info("This is first time receiving linkStateRoutingEntry from " + senderAddr + "and its content is empty, so no need to addRoutingEntrySet"); return; } } this.linkStateRoutingInfo.addForwardedRoutingEntrySet(routingEntrySet); //this.log.debug("addForwardedRoutingEntrySet() is called becaused linkStateRoutingEntry update received from " + this.publisherAddr); boolean updateForwaringTable = this.linkStateRoutingInfo.addRoutingEntrySet(routingEntrySet); if(updateForwaringTable) // information changes, update forwarding table { this.log.debug("linkStateRoutingEntry received, and updateForwaringTable is true, so update FT"); this.linkStateRoutingInfo.buildForwrdingTable(); }else { // System.out.println("linkStateRoutingEntry received, nothing changed: " + this.linkStateRoutingInfo.getMap()); // System.out.println("linkStateRoutingEntry received, nothing changed: " + this.forwardingTable.getForwardingTable()); } }else if(this.attribute.equals("linkStateRoutingEntryNeighborsReceived")) { try { routingEntrySetForwardedByNeighbor_t routingEntrySetForwardedByNeighbor = routingEntrySetForwardedByNeighbor_t.parseFrom(value); int num = routingEntrySetForwardedByNeighbor.getRoutingEntrySetForwardedByNeighborCount(); // this.log.debug("linkStateRoutingEntryNeighborsReceived pub event received has " + num + " entries inside, from " + this.publisherAddr); boolean updateForwaringTable = false; for(int i = 0; i < num ; i++ ) { //System.out.println("000000000000000000000000000000 i is " + i ); routingEntrySet_t routingEntrySet = routingEntrySetForwardedByNeighbor.getRoutingEntrySetForwardedByNeighbor(i); //this.printRoutingEntrySet(routingEntrySet); this.linkStateRoutingInfo.addForwardedRoutingEntrySet(routingEntrySet); boolean result = this.linkStateRoutingInfo.addRoutingEntrySet(routingEntrySet); updateForwaringTable = updateForwaringTable || result; } if(updateForwaringTable) // information changes, update forwarding table { this.log.debug("linkStateRoutingEntryNeighborsReceived received, and updateForwaringTable is true, so update FT"); this.linkStateRoutingInfo.buildForwrdingTable(); }else { //System.out.println("linkStateRoutingEntryNeighborsReceived received, nothing changed: " + this.linkStateRoutingInfo.getMap()); //System.out.println("linkStateRoutingEntryNeighborsReceived received, nothing changed: " + this.forwardingTable.getForwardingTable()); } } catch (Exception e) { this.log.error(e.getMessage()); //e.printStackTrace(); //System.out.println("There is serious error here!!!!!!!!!!!!!!!!!!!!!!!!!!!"); } }else if (this.attribute.equals("checkNeighborAlive")) // check if the neighbor is alive or not { // in the Publisher.java for this event, actually the event value is the timestamp when the messgae is sent // this.log.debug("checkNeighborAlive pub event received from " + this.publisherAddr); while(this.routingDaemon == null) { this.routingDaemon = (RoutingDaemon)this.rib.getAttribute("routingDaemon"); } this.routingDaemon.updateChckNeighborTimerTask(this.publisherAddr); this.routingDaemon.addCheckNeighborTimerTask( this.publisherAddr); } } private void printRoutingEntrySet(routingEntrySet_t entrySet) { int n = entrySet.getRoutingEntrySetCount(); this.log.debug("Pub event linkStateRoutingEntryNeighborsReceived: Now print entrySet: origin's addr/timestamp:" + entrySet.getAddr() + "/" + entrySet.getTimestamp() + ", and number of the entries inside it is " + n ); for(int j = 0; j < n; j++) { LinkStateRoutingEntry entry = new LinkStateRoutingEntry(entrySet.getRoutingEntrySet(j)); this.log.debug( j + " content is: " + entry.getPrint()) ; } } //stop the event handler public void delete() { if(this.event.getEventType() == EventType.PUB) { //or stop publishing event to subscriber (Publisher thread) this.publisher.stopPub(); }else if(this.event.getEventType() == EventType.SUB) { //stop the subscription to a publisher (Send a M_STOP to publisher) } } }