/** * @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.ipc.ae; import java.util.LinkedHashMap; import java.util.LinkedList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import rina.flowAllocator.impl.FlowAllocatorImpl; import rina.irm.impl.IRMImpl; import rina.irm.util.HandleEntry; import rina.message.CDAP; import rina.message.CDAP.CDAPMessage; import rina.object.gpb.ApplicationProcessNamingInfoMessage_t.applicationProcessNamingInfo_t; import rina.object.gpb.DirectoryForwardingTableEntry_t.directoryForwardingTableEntrySet_t; import rina.object.gpb.DirectoryForwardingTableEntry_t.directoryForwardingTableEntry_t; import rina.object.gpb.EnrollmentInformation_t.enrollmentInformation_t; import rina.object.gpb.Flow_t.flow_t; import rina.object.gpb.Member_t.member_t; import rina.object.gpb.Member_t.members_t; import rina.object.gpb.Neighbour_t.neighbor_t; import rina.object.gpb.Neighbour_t.neighbors_t; import rina.object.gpb.SubscriptionEvent_t.subscriptionEvent_t; import rina.object.gpb.UnderlyingDIFs_t.underlyingDIFs_t; import rina.object.internal.ApplicationProcessNamingInfo; import rina.object.internal.DirectoryForwardingTable; import rina.object.internal.DirectoryForwardingTableEntry; import rina.object.internal.Flow; import rina.object.internal.ForwardingTable; import rina.object.internal.Member; import rina.object.internal.Neighbor; import rina.object.internal.Neighbors; import rina.rib.impl.RIBImpl; import rina.ribDaemon.impl.RIBDaemonImpl; import rina.routing.RoutingDaemon; import rina.util.FlowInfoQueue; import rina.util.MessageQueue; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; /** * Each flow (handleID) to Management AE is attached with a ManagementAEHandler * @author Yuefeng Wang. Computer Science Department, Boston University * */ public class ManagementAEHandler extends Thread { private Log log = LogFactory.getLog(this.getClass()); private boolean listen = true; private String apName = null; private String apInstance = null; private String aeName = null; private String aeInstance = null; private long rinaAddr = -1; private int handleID = -1; private String dstIPCName = null; private String dstIPCInstance = null; private int dstRINAAddr = -1; //this is an attribute to calculate who is the direct neighbor for a new ipc member // for DIF zero it is ip nework name private LinkedList<String> dstIPCUnderlyingDIFs = null; private HandleEntry he = null; private RIBImpl rib = null; private IRMImpl irm = null; private RIBDaemonImpl ribDaemon = null; private RoutingDaemon routingDaemon = null; private DirectoryForwardingTable directoryForwardingTable = null; private Neighbors neighbors = null; private LinkedHashMap<String, FlowInfoQueue> callbackApplicaitonFlowInfoQueues = null; private ForwardingTable forwardingTable = null; private String routingProtocol = null; /** * This is an authenticator AE thread * @param handleID * @param he * @param rib * @param irm */ public ManagementAEHandler ( int handleID, HandleEntry he, RIBImpl rib, IRMImpl irm) { this.handleID = handleID; this.he = he; this.apName = this.he.getSrcApName(); this.apInstance = this.he.getSrcApInstance(); this.aeName = this.he.getSrcAeName(); this.aeInstance = this.he.getSrcAeInstance(); this.dstIPCName = this.he.getDstApName(); this.dstIPCInstance = this.he.getDstApInstance(); this.rib = rib; this.irm = irm; this.ribDaemon = (RIBDaemonImpl) this.rib.getAttribute("ribDaemon"); this.directoryForwardingTable = (DirectoryForwardingTable) this.rib.getAttribute("directoryForwardingTable"); this.callbackApplicaitonFlowInfoQueues = (LinkedHashMap<String, FlowInfoQueue>)this.rib.getAttribute("callbackApplicaitonFlowInfoQueues"); this.neighbors = (Neighbors)this.rib.getAttribute("neighbors"); this.forwardingTable = ( ForwardingTable)this.rib.getAttribute("forwardingTable"); this.rinaAddr = Long.parseLong(this.rib.getAttribute("rinaAddr").toString()); this.routingProtocol = (String)this.rib.getAttribute("routingProtocol"); this.routingDaemon = (RoutingDaemon)this.rib.getAttribute("routingDaemon"); this.start(); } public void run() { this.log.info("ManagementAE Handler started on handleID " + this.handleID); while(this.listen) { byte[] msg = this.irm.receive(this.handleID); CDAP.CDAPMessage cdapMessage = null; try { cdapMessage = CDAP.CDAPMessage.parseFrom(msg); } catch (Exception e) { this.log.error(e.getMessage()); } this.processCDAPMessage(cdapMessage); } } private void processCDAPMessage(CDAPMessage cdapMessage) { // this.log.info("CDAPMessage received, and opcode is " + cdapMessage.getOpCode()); switch(cdapMessage.getOpCode()){ case M_CONNECT: this.handle_M_CONNECT(cdapMessage); break; case M_START: this.handle_M_START(cdapMessage); break; case M_STOP_R: this.handle_M_STOP_R(cdapMessage); break; case M_CREATE: this.handle_M_CREATE(cdapMessage); break; case M_CREATE_R: this.handle_M_CREATE_R(cdapMessage); break; default: break; } } private void handle_M_CREATE_R(CDAPMessage cdapMessage) { if(cdapMessage.getObjClass().equals("flow")) //this is a msg the FAI is waiting, so put in the FAI msg Queue { FlowAllocatorImpl flowAllocator = (FlowAllocatorImpl) this.rib.getAttribute("flowAllocator"); this.log.info("M_CREATE_R(flow) recevied"); CDAP.objVal_t objValue = null; flow_t flow = null; try { objValue = cdapMessage.getObjValue(); flow = flow_t.parseFrom(objValue.getByteval().toByteArray()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //check if it needs relaying. This happens for a multi-hop flow creation. long DestRINAAddr = flow.getDestinationAddress(); this.log.debug("CDAP Message M_CREATE_R(flow)'s dest RINA addr " + DestRINAAddr + ", this IPC's addr is " + this.rinaAddr); if(DestRINAAddr != this.rinaAddr) { this.relayCDAPMessage(cdapMessage,DestRINAAddr); this.log.debug(" Not for this IPC, relay CDAP message to next hop " ); return; } int dstPort = (int)flow.getDestinationPortId(); ( ( LinkedHashMap<Integer, MessageQueue> ) this.rib.getAttribute("flowQueues") ).get(dstPort).addReceive(cdapMessage.toByteArray()); } } private void handle_M_CREATE(CDAPMessage cdapMessage) { if(cdapMessage.getObjClass().equals("flow")) { FlowAllocatorImpl flowAllocator = (FlowAllocatorImpl) this.rib.getAttribute("flowAllocator"); this.log.info("M_CREATE(flow) recevied"); CDAP.objVal_t objValue = null; flow_t flow = null; try { objValue = cdapMessage.getObjValue(); flow = flow_t.parseFrom(objValue.getByteval().toByteArray()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } long DestRINAAddr = flow.getDestinationAddress(); //check if it needs relaying. This happens for a multi-hop flow creation. this.log.debug("CDAP Message M_CREATE(flow)'s dest RINA addr " + DestRINAAddr + ", this IPC's addr is " + this.rinaAddr); if(DestRINAAddr != this.rinaAddr) { this.relayCDAPMessage(cdapMessage,DestRINAAddr); this.log.debug(" Not for this IPC, relay CDAP message to next hop " ); return; } applicationProcessNamingInfo_t src = null; applicationProcessNamingInfo_t dst = null; try { src = flow.getSourceNamingInfo(); dst = flow.getDestinationNamingInfo(); } catch (Exception e1) { this.log.error(e1.getMessage()); // e.printStackTrace(); } long srcPortID = flow.getSourcePortId(); long srcAddr = flow.getSourceAddress(); String dstApName = dst.getApplicationProcessName(); String dstApInstance = dst.getApplicationProcessInstance(); String dstAeName = dst.getApplicationEntityName(); String dstAeInstance = dst.getApplicationEntityInstance(); String srcApName = src.getApplicationProcessName(); String srcApInstance = src.getApplicationProcessInstance(); String srcAeName = src.getApplicationEntityName(); String srcAeInstance = src.getApplicationEntityInstance(); this.log.debug("DEST info: " + dstApName + "/" + dstApInstance + "/" + dstAeName + "/" + dstAeInstance); this.log.debug("SRC info: " + srcApName + "/" + srcApInstance + "/" + srcAeName + "/" + srcAeInstance); ApplicationProcessNamingInfo srcApInfo = null; ApplicationProcessNamingInfo dstApInfo = null; if(dstApInstance == "") //only apName is used { dstApInfo = new ApplicationProcessNamingInfo(dstApName); srcApInfo = new ApplicationProcessNamingInfo(srcApName); } if(dstAeName == "" && dstAeInstance =="" ) // only apName and apInstance is used { dstApInfo = new ApplicationProcessNamingInfo(dstApName, dstApInstance); srcApInfo = new ApplicationProcessNamingInfo(srcApName, srcApInstance); }else // all apName, apInstance, aeName, aeInstance are used, for now this means this app is an IPC process { dstApInfo = new ApplicationProcessNamingInfo(dstApName, dstApInstance, dstAeName, dstAeInstance); srcApInfo = new ApplicationProcessNamingInfo(srcApName, srcApInstance, srcAeName, srcAeInstance); } Flow flowRequest = new Flow(dstApInfo,srcApInfo); flowRequest.setDstAddr(srcAddr); flowRequest.setDstPortID(srcPortID); flowRequest.setUnderlyingIPCName(this.apName); flowRequest.setUnderlyingIPCInstance(this.apInstance); //call flowAllocator API to process this flow request int flowID = flowAllocator.receiveAllocationRequest(flowRequest); flowRequest.print(); //String key = dstApName + dstApInstance + dstAeName + dstAeInstance; //TESTME String key = dstApName + dstApInstance; //told the application, an incoming flow created this.log.debug("key is " + key); if(this.callbackApplicaitonFlowInfoQueues.containsKey(key)) { System.out.println("this.callbackApplicaitonFlowInfoQueues.containsKey(key): true"); }else { System.out.println("this.callbackApplicaitonFlowInfoQueues.containsKey(key): false"); } this.callbackApplicaitonFlowInfoQueues.get(key).addFlowInfo(flowRequest); this.log.debug("flowID is " + flowID); }else if(cdapMessage.getObjClass().equals("directoryforwardingtableentry set")) { directoryForwardingTableEntrySet_t sets = null; try { sets = directoryForwardingTableEntrySet_t.parseFrom(cdapMessage.getObjValue().getByteval()); } catch (InvalidProtocolBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); } int num = sets.getDirectoryForwardingTableEntryCount(); this.log.info( num + " directoryforwardingtable entry received." ); //the one is used to update its neighbors directoryForwardingTableEntrySet_t.Builder sets_to_send = directoryForwardingTableEntrySet_t.newBuilder(); for(int i =0 ;i < num; i++) { directoryForwardingTableEntry_t entry = sets.getDirectoryForwardingTableEntry(i); applicationProcessNamingInfo_t apInfo_t = entry.getApplicationName(); String apName = apInfo_t.getApplicationProcessName(); String apInstance = apInfo_t.getApplicationProcessInstance(); ApplicationProcessNamingInfo apInfo = null; if(apInstance == "") //apIntance may not be used for application { apInfo = new ApplicationProcessNamingInfo(apName); }else //if application is an IPC, then apInstance is used for sure { apInfo = new ApplicationProcessNamingInfo(apName, apInstance); } DirectoryForwardingTableEntry directoryForwardingTableEntry = new DirectoryForwardingTableEntry(apInfo, entry.getIpcProcessAddress(), entry.getTimestamp()); directoryForwardingTableEntry.print(); if( this.directoryForwardingTable.checkEntry(directoryForwardingTableEntry) == false ) //it does not contains this entry { this.directoryForwardingTable.addEntry(directoryForwardingTableEntry); this.log.debug("directoryForwardingTableEntry added info (apName/apInstance/ipcaddr/timestamp): " + apName + "/" + apInstance + "/" + entry.getIpcProcessAddress() + "/" + entry.getTimestamp()); sets_to_send.addDirectoryForwardingTableEntry(entry); }else { this.log.debug("DirectoryForwardingTableEntry received exists, discarded"); } } directoryForwardingTableEntrySet_t send = sets_to_send.buildPartial(); // send update to its neighbors if(send.getDirectoryForwardingTableEntryCount() >=1) { this.log.debug("There exists new entry sending to neighbors"); LinkedList<Neighbor> neighborList = this.neighbors.getNeighborList(); for(int j = 0; j< neighborList.size(); j++ ) { Neighbor neighbor = neighborList.get(j); String dstipcName = neighbor.getApName(); String dstipcInstance = neighbor.getApInstance(); int handle = this.irm.allocateFlow(this.apName, this.apInstance, "Management", "1", dstipcName, dstipcInstance, "Management", "1"); CDAP.objVal_t.Builder objM_CREATE_directoryforwardingtableentries = CDAP.objVal_t.newBuilder(); objM_CREATE_directoryforwardingtableentries.setByteval(ByteString.copyFrom(send.toByteArray())); CDAP.CDAPMessage M_CREATE = rina.message.CDAPMessageGenerator.generateM_CREATE ( "directoryforwardingtableentry set", "/dif/management/flowallocator/directoryforwardingtableentries", objM_CREATE_directoryforwardingtableentries.buildPartial(), 56 ); try { this.irm.send(handle, M_CREATE.toByteArray()); this.log.debug("M_CREATE(directoryforwardingtableentry set) updates sent over handle " + handle); } catch (Exception e) { // TODO Auto-generated catch block this.log.error(e.getMessage()); } } }else { this.log.debug("No new entry sending to neighbors"); } }else if(cdapMessage.getObjClass().equals("neighbor set")) //new direct neighbor joins the DIF { neighbors_t neighbors_obj = null; try { neighbors_obj = neighbors_t.parseFrom(cdapMessage.getObjValue().getByteval()); } catch (InvalidProtocolBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); } int num = neighbors_obj.getNeighborCount(); this.log.info(num + " neihgbor entry received." ); for(int i =0 ;i < num; i++) { neighbor_t neighbor_obj = neighbors_obj.getNeighbor(i); String apName = neighbor_obj.getApplicationProcessName(); String apInstance = neighbor_obj.getApplicationProcessInstance(); long addr = neighbor_obj.getAddress(); Neighbor neighbor = new Neighbor(apName,apInstance,addr); //add direct neighbor to its forwarding table //this is bootstrap this.forwardingTable.addNextHop((int)neighbor.getAddr(), (int) neighbor.getAddr()); boolean existBefore = this.neighbors.addNeighbor(neighbor); if(!existBefore) //new neighbor, subscribte to its routing entry { while(this.routingDaemon == null) { this.routingDaemon = (RoutingDaemon)this.rib.getAttribute("routingDaemon"); } if(this.routingProtocol.equals("linkState")) { this.routingDaemon.addLinkStateRoutingEntrySubEvent( Long.toString(neighbor.getAddr() ) ); }else if(this.routingProtocol.equals("distanceVector")) { //TODO } } this.log.debug("neighbor entry added info (apName/apInstance/addr): " + apName + "/" + apInstance + "/" + addr); } }else if(cdapMessage.getObjClass().equals("subscription")) { // this.log.debug("M_CREAET (subscription) received "); try { subscriptionEvent_t event_t = subscriptionEvent_t.parseFrom(cdapMessage.getObjValue().getByteval()); this.ribDaemon.handleReceivedSubscription(event_t); } catch (InvalidProtocolBufferException e) { this.log.error(e.getMessage()); } }else if(cdapMessage.getObjClass().equals("member set")) { members_t sets = null; try { sets = members_t.parseFrom(cdapMessage.getObjValue().getByteval()); } catch (InvalidProtocolBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); } int num = sets.getMemberCount(); this.log.debug( num + " member entry recevied ." ); //the one is used to update its neighbors members_t.Builder sets_to_send = members_t.newBuilder(); for(int i =0 ;i < num; i++) { member_t entry = sets.getMember(i); String IPCApName = entry.getApplicationProcessName(); String IPCApInstance = entry.getApplicationProcessInstance(); int addr = (int) entry.getAddress(); if(this.rib.containMember(IPCApName, IPCApInstance, addr)) { this.log.debug("Discard, the rib already has information(member list) about the IPC: " + IPCApName + "/" + IPCApInstance + "/" + addr); }else { LinkedList<String> underlyingDIFs = new LinkedList<String> (); for(int count = 0 ; count < entry.getUnderlyingDIFsCount(); count++) { underlyingDIFs.add(entry.getUnderlyingDIFs(count)); } this.rib.addMember(addr, IPCApName, IPCApInstance,underlyingDIFs ); this.log.debug("The rib updates its information(member list) about the IPC: " + IPCApName + "/" + IPCApInstance + "/" + addr + "/" +underlyingDIFs ); ////////////////////////////////////////////////////////////////////////////////////////////// //check if any member is its direct neighbor, if so, add to direct neighbor and sub to it LinkedList<String> itselfUnderlyingDIF = ( LinkedList<String> )this.rib.getAttribute("underlyingDIFs"); System.out.println("itselfUnderlyingDIF is " + itselfUnderlyingDIF + ", and underlyingDIFs is " + underlyingDIFs); for(int counter = 0; counter < underlyingDIFs.size(); counter++) { if(itselfUnderlyingDIF.contains(underlyingDIFs.get(counter))) // they have common underlying DIF, it is direct neighbor { Neighbor neighbor = new Neighbor(IPCApName,IPCApInstance,addr); //add direct neighbor to its forwarding table //this is bootstrap this.forwardingTable.addNextHop((int)neighbor.getAddr(), (int) neighbor.getAddr()); boolean existBefore = this.neighbors.addNeighbor(neighbor); if(!existBefore) //new neighbor, subscribe to its routing entry { while(this.routingDaemon == null) { this.routingDaemon = (RoutingDaemon)this.rib.getAttribute("routingDaemon"); } if(this.routingProtocol.equals("linkState")) { this.routingDaemon.addLinkStateRoutingEntrySubEvent( Long.toString(neighbor.getAddr() ) ); }else if(this.routingProtocol.equals("distanceVector")) { //TODO } } this.log.debug("member set received, and found new direct neighbor,neighbor entry added info (apName/apInstance/addr): " + apName + "/" + apInstance + "/" + addr); break;//no need to check the rest underlying DIFs } } /////////////////////////////////////////////////////////////////////////////////////////////// //send the info to its neighbors member_t.Builder entry_to_send = member_t.newBuilder(); entry_to_send.setAddress(addr); entry_to_send.setApplicationProcessInstance(IPCApInstance); entry_to_send.setApplicationProcessName(IPCApName); for(int count = 0 ; count < entry.getUnderlyingDIFsCount(); count++) { entry_to_send.addUnderlyingDIFs(entry.getUnderlyingDIFs(count)); } sets_to_send.addMember(entry_to_send.buildPartial()); } } members_t send = sets_to_send.buildPartial(); // send update to its neighbors if(send.getMemberCount() >=1) { this.log.debug("There exists new DIF member entry sending to neighbors"); LinkedList<Neighbor> neighborList = this.neighbors.getNeighborList(); for(int j = 0; j< neighborList.size(); j++ ) { Neighbor neighbor = neighborList.get(j); String dstipcName = neighbor.getApName(); String dstipcInstance = neighbor.getApInstance(); int handle = this.irm.allocateFlow(this.apName, this.apInstance, "Management", "1", dstipcName, dstipcInstance, "Management", "1"); CDAP.objVal_t.Builder objM_CREATE_directoryforwardingtableentries = CDAP.objVal_t.newBuilder(); objM_CREATE_directoryforwardingtableentries.setByteval(ByteString.copyFrom(send.toByteArray())); CDAP.CDAPMessage M_CREATE = rina.message.CDAPMessageGenerator.generateM_CREATE ( "member set", "/dif/management/members", objM_CREATE_directoryforwardingtableentries.buildPartial(), 56 ); try { this.irm.send(handle, M_CREATE.toByteArray()); this.log.debug("M_CREATE(member set) updates sent over handle " + handle + " to " + dstipcName + "/" + dstipcInstance ); } catch (Exception e) { // TODO Auto-generated catch block this.log.error(e.getMessage()); } } }else { this.log.debug("No new member set entry sending to neighbors"); } } } private void relayCDAPMessage(CDAPMessage cdapMessage, long dstRINAAddr) { //here dstRINAAddr must be casted to int, otherwise the search in forwardingtable will return null //as forwarding table is in format of <Integer, Integer> long nextHop = this.forwardingTable.getNextHop((int)dstRINAAddr); //this.log.debug("next hop of " + dstRINAAddr + " is " + nextHop); Neighbor neighbor = this.neighbors.getBeighbor(nextHop); if( neighbor == null) { this.log.error("Next hop does not exsit"); } int handleID = this.irm.allocateFlow(this.apName,this.apInstance, "Management", "1", neighbor.getApName(),neighbor.getApInstance(), "Management", "1"); try { this.irm.send(handleID, cdapMessage.toByteArray()); this.log.info( " M_CREATE_R (flow) sent out over handleID " + handleID); } catch (Exception e) { this.log.info( "M_CREATE_R(flow) sent error"); return; } } private void handle_M_CONNECT(CDAPMessage cdapMessage) { int result = 0; if(cdapMessage.getAuthMech() == CDAP.authTypes_t.AUTH_PASSWD) { this.log.debug("M_CONNECT with AUTH_PASSWD received"); CDAP.authValue_t authValue = cdapMessage.getAuthValue(); String userName = authValue.getAuthName(); String passWord = authValue.getAuthPassword(); result = this.authenticate(userName, passWord); // use this underlyingDIF info to calculate neighbors this.dstIPCUnderlyingDIFs = new LinkedList<String>(); underlyingDIFs_t list; try { list = underlyingDIFs_t.parseFrom(authValue.getAuthOther()); for(int i =0; i < list.getUnderlyingDIFsCount();i++) { this.dstIPCUnderlyingDIFs.add(list.getUnderlyingDIFs(i)); //System.out.println("dstIPCUnderlyingDIFs " + i + " is " + list.getUnderlyingDIFs(i)); } } catch (InvalidProtocolBufferException e) { this.log.error(e.getMessage()); } this.log.debug("Enrollment info received in M_CONNECT - userName/passWord/underlyingDIFs: " + userName + "/" + passWord + "/" + this.dstIPCUnderlyingDIFs); }else if(cdapMessage.getAuthMech() == CDAP.authTypes_t.AUTH_NONE) { result = 0;//true all the time }else { //Implement your own policy here //result = } CDAP.CDAPMessage M_CONNECT_R = rina.message.CDAPMessageGenerator.generateM_CONNECT_R ( cdapMessage.getAbsSyntax(), result, cdapMessage.getAuthMech(), "enrollment information", "/daf/management/enrollment", cdapMessage.getSrcAEInst(), cdapMessage.getSrcAEName(), cdapMessage.getSrcApInst(), cdapMessage.getSrcApName(), cdapMessage.getInvokeID(), cdapMessage.getDestAEInst(), cdapMessage.getDestAEName(), cdapMessage.getDestApInst(), cdapMessage.getDestApName(), cdapMessage.getVersion() ); try { this.irm.send(this.handleID, M_CONNECT_R.toByteArray()); this.log.debug("M_CONNECT_R sent: " + cdapMessage.getSrcApName() + "/" + cdapMessage.getSrcApInst() + "/"+cdapMessage.getSrcAEName() + "/" + cdapMessage.getSrcAEInst()); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } /** * * @param userName * @param passWord * @return */ private int authenticate(String userName, String passWord) { if(userName.equals("BU") && passWord.equals("BU")) { return 0;//true }else { return -1; //false } } private void handle_M_START(CDAPMessage cdapMessage) { if(cdapMessage.getObjClass().equals("enrollment information")) { enrollmentInformation_t ei_msg= null; try { ei_msg = enrollmentInformation_t.parseFrom(cdapMessage.getObjValue().getByteval()); } catch (InvalidProtocolBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); } //generate the internal RINA Address for the new member this.dstRINAAddr = this.rib.addMember(this.he.getDstApName(), this.he.getDstApInstance(), this.dstIPCUnderlyingDIFs) ; //add underlying DIF info of this ipc //note dstIPCUnderlyingDIFs is got in the M_CONNECT message's authenValue //this.rib.addUnderlyingDIFsInfo(this.dstRINAAddr, this.dstIPCUnderlyingDIFs); //add the new member to its direct neighbors Neighbor neighbor = new Neighbor(this.he.getDstApName(), this.he.getDstApInstance(),this.dstRINAAddr); //( (Neighbors)rib.getAttribute("neighbors") ).addNeighbor(neighbor); this.neighbors.addNeighbor(neighbor); // System.out.println("ttttttttttttttthis.dstRINAAddr enrolled into the dif, its addr " + this.dstRINAAddr ); //Note: subscription to the new member's routing entry is done when M_STOP_R is received //add direct neighbor to its forwarding table //this is bootstrap this.forwardingTable.addNextHop((int)neighbor.getAddr(), (int) neighbor.getAddr()); CDAP.objVal_t.Builder obj = CDAP.objVal_t.newBuilder(); obj.setInt64Val(this.dstRINAAddr); CDAP.CDAPMessage M_START_R = rina.message.CDAPMessageGenerator.generateM_START_R ( 0, "address", "/daf/management/naming/address", obj.buildPartial(), cdapMessage.getInvokeID() ); try { this.irm.send(this.handleID, M_START_R.toByteArray()); this.log.debug("M_START_R(address) sent " ); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } ////////////////////////////////////////////////////////////////////////////////// //(1)send to the new member its current DIF member list members_t.Builder memberList_to_send = members_t.newBuilder(); LinkedList<Member> difMemberList = this.rib.getMemberEntryList(); for(int i = 0; i < difMemberList.size(); i++) { memberList_to_send.addMember(difMemberList.get(i).convert()); } CDAP.objVal_t.Builder objM_CREATE_Members = CDAP.objVal_t.newBuilder(); objM_CREATE_Members.setByteval(ByteString.copyFrom(memberList_to_send.buildPartial().toByteArray())); CDAP.CDAPMessage M_CREATE_Members = rina.message.CDAPMessageGenerator.generateM_CREATE ( "member set", "/dif/management/members", objM_CREATE_Members.buildPartial(), 56 ); try { this.irm.send(this.handleID, M_CREATE_Members.toByteArray()); this.log.debug("M_CREATE(member set)sent" ); } catch (Exception e1) { // TODO Auto-generated catch block this.log.error(e1.getMessage()); //e1.printStackTrace(); } //(2)also send to its neighbors about the new member LinkedList<Neighbor> neighborList = this.neighbors.getNeighborList(); members_t.Builder member_update = members_t.newBuilder(); Member member_new = new Member(this.dstIPCName, this.dstIPCInstance, this.dstRINAAddr, this.dstIPCUnderlyingDIFs); member_new.print(); member_update.addMember(member_new.convert()); CDAP.objVal_t.Builder objM_CREATE_directoryforwardingtableentries = CDAP.objVal_t.newBuilder(); objM_CREATE_directoryforwardingtableentries.setByteval(ByteString.copyFrom(member_update.buildPartial().toByteArray())); CDAP.CDAPMessage M_CREATE_updateMember = rina.message.CDAPMessageGenerator.generateM_CREATE ( "member set", "/dif/management/members", objM_CREATE_directoryforwardingtableentries.buildPartial(), 56 ); for(int j = 0; j< neighborList.size(); j++ ) { Neighbor dstNeighbor = neighborList.get(j); String dstipcName = dstNeighbor.getApName(); String dstipcInstance = dstNeighbor.getApInstance(); if(dstipcName.equals(this.dstIPCName) && dstipcInstance.equals(this.dstIPCInstance)) { continue; // no need to send to the new member, as it is also the enroller's neighbor } int handle = this.irm.allocateFlow(this.apName, this.apInstance, "Management", "1", dstipcName, dstipcInstance, "Management", "1"); try { this.irm.send(handle, M_CREATE_updateMember.toByteArray()); this.log.debug("New member joined the DIF, so M_CREATE(member set) updates sent over handle " + handle + " to neighbor " + dstipcName + "/" + dstipcInstance ); } catch (Exception e) { // TODO Auto-generated catch block this.log.error(e.getMessage()); } } //send to the new member its the neighbors, based on its underlying DIF (or underlying Internet name) neighbors_t neighbors = this.calculateNeighbors(); CDAP.objVal_t.Builder objM_CREATE_Neighbour = CDAP.objVal_t.newBuilder(); objM_CREATE_Neighbour.setByteval(ByteString.copyFrom(neighbors.toByteArray())); CDAP.CDAPMessage M_CREATE = rina.message.CDAPMessageGenerator.generateM_CREATE ( "neighbor set", "/daf/management/neighbors", objM_CREATE_Neighbour.buildPartial(), 56 ); try { this.irm.send(this.handleID, M_CREATE.toByteArray()); this.log.debug("M_CREATE(neighbour set)sent" ); } catch (Exception e1) { // TODO Auto-generated catch block this.log.error(e1.getMessage()); //e1.printStackTrace(); } //send all existing reachable applications(directory forwarding table) //if any if(this.directoryForwardingTable.getSize() > 0) { CDAP.objVal_t.Builder objM_CREATE_DFT = CDAP.objVal_t.newBuilder(); objM_CREATE_DFT.setByteval(ByteString.copyFrom(this.directoryForwardingTable.convert().toByteArray())); CDAP.CDAPMessage M_CREATE_DFT = rina.message.CDAPMessageGenerator.generateM_CREATE ( "directoryforwardingtableentry set", "/dif/management/flowallocator/directoryforwardingtableentries", objM_CREATE_DFT.buildPartial(), 56 ); try { this.irm.send(this.handleID, M_CREATE_DFT.toByteArray()); this.log.debug("M_CREATE(directoryforwardingtableentry set)sent" ); } catch (Exception e1) { // TODO Auto-generated catch block this.log.error(e1.getMessage()); //e1.printStackTrace(); } } //send M_STOP enrollment CDAP.objVal_t.Builder objM_STOP = CDAP.objVal_t.newBuilder(); objM_STOP.setBoolval(true); CDAP.CDAPMessage M_STOP = rina.message.CDAPMessageGenerator.generateM_STOP ( "enrollment information", "/daf/management/enrollment", objM_STOP.buildPartial(), 54 ); try { this.irm.send(this.handleID, M_STOP.toByteArray()); this.log.debug("M_STOP sent " ); } catch (Exception e1) { // TODO Auto-generated catch block this.log.error(e1.getMessage()); //e1.printStackTrace(); } } } //calculate neighbor of the members based on its underlying DIF info private neighbors_t calculateNeighbors() { //this returns all ipc using the same underlying DIF, including the new ipc itself neighbors_t.Builder neighbours_toSend = neighbors_t.newBuilder(); int num = this.dstIPCUnderlyingDIFs.size(); this.log.debug("calculateNeighbors(): the new IPC member has " + num + " underlying DIFs, and they are " + this.dstIPCUnderlyingDIFs); for(int j=0; j < num ;j++) { LinkedList<Neighbor> neighbors = this.rib.getIPCListOfUnderlyingDIFName(this.dstIPCUnderlyingDIFs.get(j)); // System.out.println(" nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnneighbors.size() is " + neighbors.size()); for(int i = 0; i< neighbors.size();i++) { Neighbor neighbor = neighbors.get(i); // System.out.println("iiiiiiiiiiiiiiiiiiiiiiii is " + i); //remove the new ipc itself, since it is not its own neighbor if(neighbor.getAddr() == this.dstRINAAddr) {continue;} neighbor.print(); neighbours_toSend.addNeighbor(neighbor.convert()); //NOTE: here we don't send M_CREATE(neighbour set), instead we use the member set update to update everyone possible direct neighbors // when a membe set M_CREATE is received, every ipc check the new member's underlying DIFs info, to see if it is a direct neighbor //then sub to it as regular /* //update everyone with this new neighbor information ////////////////////////////////////////////////////////////////////////////////////// String dstipcName = neighbor.getApName(); String dstipcInstance = neighbor.getApInstance(); int dstAddr = (int) neighbor.getAddr(); //this is the authenticator itself, no need to send if(dstipcName.equals(this.apName) && dstipcInstance.equals(this.apInstance)) {continue;} int handle = this.irm.allocateFlow(this.apName, this.apInstance, "Management", "1", dstipcName, dstipcInstance, "Management", "1"); CDAP.objVal_t.Builder objM_CREATE_Neighbour = CDAP.objVal_t.newBuilder(); neighbors_t.Builder neighbors_to_send = neighbors_t.newBuilder(); neighbors_to_send.addNeighbor( new Neighbor(this.dstIPCName, this.dstIPCInstance, this.dstRINAAddr).convert()); objM_CREATE_Neighbour.setByteval(ByteString.copyFrom(neighbors_to_send.buildPartial().toByteArray())); CDAP.CDAPMessage M_CREATE = message.generator.CDAPMessage.generateM_CREATE ( "neighbor set", "/daf/management/neighbors", objM_CREATE_Neighbour.buildPartial(), 56 ); try { this.irm.send(handle, M_CREATE.toByteArray()); this.log.debug("M_CREATE(neighbour set) update sent, due to new member joining the DIF, new member info " + this.dstIPCName + "/" + this.dstIPCInstance + "/" + this.dstRINAAddr); } catch (Exception e1) { this.log.error(e1.getMessage()); } ////////////////////////////////////////////////////////////////////////////////////// */ } } return neighbours_toSend.buildPartial(); } private void handle_M_STOP_R(CDAPMessage cdapMessage) { if(cdapMessage.getObjClass().equals("enrollment information")) { if(cdapMessage.getResult() == 0) { CDAP.CDAPMessage M_START = rina.message.CDAPMessageGenerator.generateM_START( "operationstatus", "/daf/management/operationalStatus", 0); try { this.irm.send(this.handleID, M_START.toByteArray() ); this.log.debug("M_START (operationstatus) sent " ); this.log.debug("New member is enrolled into the DIF on handleID " + this.handleID ); //subscribe to the new member's routing entry if(this.routingProtocol.equals("linkState")) { this.routingDaemon.addLinkStateRoutingEntrySubEvent( Long.toString(this.dstRINAAddr) ); }else if(this.routingProtocol.equals("distanceVector")) { //TODO } } catch (Exception e1) { // TODO Auto-generated catch block this.log.error(e1.getMessage()); //e1.printStackTrace(); } } } } }