/** * @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.idd; import java.util.LinkedHashMap; import java.util.LinkedList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.google.protobuf.InvalidProtocolBufferException; import rina.object.gpb.IDDMessage_t.iddMessage_t; import rina.object.gpb.IDDMessage_t.opCode_t; import rina.object.internal.ApplicationProcessNamingInfo; import rina.object.internal.IDDRecord; import rina.object.internal.IDDRecord.AppRecord; import rina.rib.impl.RIBImpl; import rina.tcp.TCPFlow; /** * IDD process creates an IDDHanlder for each process communicating with it * * @author Yuefeng Wang. Computer Science Department, Boston University * */ public class IDDHandler extends Thread { private Log log = LogFactory.getLog(this.getClass()); private RIBImpl rib = null; private TCPFlow clientFlow = null; private boolean stop = false; //For DIF, key is DIF name //For APP, key is apName + apInstance private LinkedHashMap<String, IDDRecord> iddDatabase = null; public IDDHandler(TCPFlow clientFlow, RIBImpl rib) { this.clientFlow = clientFlow; this.rib = rib; this.iddDatabase = (LinkedHashMap<String, IDDRecord>) this.rib.getAttribute("iddDatabase"); } public void run() { byte[] msg = null; while(!stop) { try { msg = this.clientFlow.receive(); } catch (Exception e) { //this.log.error(e.getMessage()); this.log.info("IDD handler stopped due to exception."); return; } this.handleReceivedMessage(msg); } } private void handleReceivedMessage(byte[] msg) { iddMessage_t IDDMsg = null; try { IDDMsg = iddMessage_t.parseFrom(msg); } catch (InvalidProtocolBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); return; } this.log.debug("IDD message received with opcode " + IDDMsg.getOpCode()); if(IDDMsg.getOpCode().toString().equals("Request")) { this.handleRequest(IDDMsg); }else if (IDDMsg.getOpCode().toString().equals("Register")) { this.handleRegister(IDDMsg); }else { this.log.error("IDD Message cannot be handled"); } } //handle register message private void handleRegister(iddMessage_t iddMsg) { IDDRecord iddRecord = null; if(iddMsg.hasDifName()) //DIF reg { //For DIF, key is DIFName String DIFName = iddMsg.getDifName(); this.log.debug("DIFName is " + DIFName); if(!this.iddDatabase.containsKey(DIFName)) //New Entry { iddRecord = new IDDRecord(iddMsg); this.iddDatabase.put(DIFName,iddRecord); }else { //remember one DIF may have multiple authenticator, which means IDD may receive REG message from different //IPC process for same DIF iddRecord = this.iddDatabase.get(DIFName); //update timestamp, basically it is the last time the record is modified if(iddRecord.getTimeStamp() <= iddMsg.getTimeStamp()) { iddRecord.setTimeStamp(iddMsg.getTimeStamp()); } LinkedList<ApplicationProcessNamingInfo> authNameList = iddRecord.getAuthenticatorNameInfoList(); //FIXME: Here we don't remove the duplicate record, //so the queryer later have to deal with this once they got an response for(int i = 0; i < iddMsg.getAuthenticatorNameInfoCount(); i++) { authNameList.add(new ApplicationProcessNamingInfo ( iddMsg.getAuthenticatorNameInfo(i) ) ); } } }else //APP reg { //this can be application name or service name //For service name, such as "relay" service ApplicationProcessNamingInfo appInfo = new ApplicationProcessNamingInfo ( iddMsg.getApplicationNameInfo() ); String apName = appInfo.getApName(); String apInstance = appInfo.getApInstance(); //For app, key is apName + apInstance String key = apName + apInstance; if(!iddDatabase.containsKey(key)) //New Entry { iddRecord = new IDDRecord(iddMsg); this.iddDatabase.put(key, iddRecord); }else { iddRecord = this.iddDatabase.get(key); //update timestamp, basically it is the last time the record is modified if(iddRecord.getTimeStamp() <= iddMsg.getTimeStamp()) { iddRecord.setTimeStamp(iddMsg.getTimeStamp()); } LinkedList<AppRecord> appRecordList = iddRecord.getAppRecordList(); for(int i = 0 ; i < iddMsg.getIddResponseCount(); i++) { iddRecord.addAppRecord(iddMsg.getIddResponse(i)) ; } } } this.log.debug("REG new IDD entry added"); iddRecord.print(); } //handle IDD Request (query) message and send back Response message private void handleRequest(iddMessage_t iddMsg) { String key = null; if(iddMsg.hasDifName()) //DIF Name query { key = iddMsg.getDifName(); }else // APP query { key = iddMsg.getApplicationNameInfo().getApplicationProcessName() + iddMsg.getApplicationNameInfo().getApplicationProcessInstance(); } int result = -1; // 0 true // 1 false iddMessage_t.Builder responseMsg = iddMessage_t.newBuilder(); responseMsg.setOpCode(opCode_t.Response); if(this.iddDatabase.containsKey(key)) { result = 0; responseMsg.setResult(result); IDDRecord iddRecord = this.iddDatabase.get(key); if(iddRecord.getType().toString().equals("DIF")) //DIF response { responseMsg.setDifName(iddRecord.getDIFName()); //POLICY HOLDER //return all authenticators //YOU can implement your own policy for(int i = 0; i < iddRecord.getAuthenticatorNameInfoList().size(); i++) { responseMsg.addAuthenticatorNameInfo(iddRecord.getAuthenticatorNameInfoList().get(i).convert()); } }else //APP response { responseMsg.setApplicationNameInfo(iddRecord.getApplicationProcessInfo().convert()); for(int i = 0; i < iddRecord.getAppRecordList().size(); i++) { responseMsg.addIddResponse(iddRecord.getAppRecordList().get(i).convert()); } } responseMsg.setTimeStamp(iddRecord.getTimeStamp()); }else { result = 1; // no such key exist responseMsg.setResult(result); } try { this.clientFlow.send(responseMsg.buildPartial().toByteArray()); this.log.info("IDD reponse sent"); } catch (Exception e) { this.log.error(e.getMessage()); e.printStackTrace(); } } }