/**
* @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.tcp.util;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import rina.irm.util.HandleEntry;
import rina.rib.impl.RIBImpl;
import rina.tcp.TCPFlow;
import rina.util.MessageQueue;
/**
* This is to store all TCP flows allocated
* @author Yuefeng Wang. Computer Science Department, Boston University
* @version 1.0
*/
public class TCPFlowAllocated {
private Log log = LogFactory.getLog(TCPFlowAllocated.class);
private RIBImpl rib = null;
private LinkedHashMap<Integer, TCPFlow> tcpFlowAllocated = null;
private LinkedHashMap<Integer, MessageQueue> tcpFlowMsgQueue = null;
private int flowIDRange = 10000;
//between two applications there is only one wire
// the key "name" = src application name + dst application name (BU wire case)
// Or src application name + src entity name + dst application name + dst entity name (RINA community)
private LinkedHashMap<String, Integer> nameToFlowID = null;
//Only used for RINA community case
//the following attributes are not used for BU case
private String ApName = null;
private String ApInstance = "1"; // by default
//BU case use this
private LinkedHashMap<Integer, WireListenerTCP> wireListeners = null;
//RINA community case use this
private WellKnownRINAAddr wellKnownRINAAddr = null;
/**
* BU case
*/
public TCPFlowAllocated(RIBImpl rib)
{
this.tcpFlowAllocated = new LinkedHashMap<Integer, TCPFlow> ();
this.tcpFlowMsgQueue = new LinkedHashMap<Integer, MessageQueue> ();
this.nameToFlowID = new LinkedHashMap<String,Integer> ();
this.rib = rib;
this.wireListeners = new LinkedHashMap<Integer, WireListenerTCP>();
}
/**
* This is used when talking with RINA community
* @param ApName
* @param ApInstance
* @param AeName
*/
public TCPFlowAllocated(String ApName, String ApInstance)
{
this.tcpFlowAllocated = new LinkedHashMap<Integer, TCPFlow> ();
this.tcpFlowMsgQueue = new LinkedHashMap<Integer, MessageQueue> ();
this.nameToFlowID = new LinkedHashMap<String,Integer> ();
this.ApName = ApName;
if(ApInstance!=null)
{
this.ApInstance = ApInstance;
}
this.wellKnownRINAAddr = new WellKnownRINAAddr(ApName, ApInstance);
}
/**
* Name is the concatenation of srcName + dstName
* @param name
* @param tcpFlow
* @return
*/
public synchronized int addTCPFlow(String name, TCPFlow tcpFlow)
{
int flowID = this.generateFlowId();
this.nameToFlowID.put(name, flowID);
tcpFlow.setFlowID(flowID);
this.tcpFlowAllocated.put(flowID, tcpFlow);
this.tcpFlowMsgQueue.put(flowID, tcpFlow.getMsgQueue());
this.log.info(" TCP flow to " + name + " added with flowID " + flowID);
return flowID;
}
public synchronized void removeTCPFlow(int flowID)
{
TCPFlow flow = this.tcpFlowAllocated.get(flowID);
String src = flow.getSrcName();
String dst = flow.getDstName();
this.nameToFlowID.remove(src+dst);
flow.close();
this.tcpFlowAllocated.remove(flowID);
this.tcpFlowMsgQueue.remove(flowID);
this.log.info(" TCP flow " + flowID + "removed because of the TCP flow creation failed");
}
/**
* This will return the first flow allocated between two applications or application entities
* since there might be multiple flows
* @param name
* @return
*/
public synchronized TCPFlow getTCPFlow(String name)
{
if( this.nameToFlowID.containsKey(name) )
{
return this.tcpFlowAllocated.get(this.nameToFlowID.get(name));
}else
{
return null;
}
}
/**
* This will return the first flow id allocated between two applications or application entities
* since there might be multiple flows
* @param name
* @return
*/
public synchronized int getTCPFlowID(String name)
{
if( this.nameToFlowID.containsKey(name) )
{
return this.nameToFlowID.get(name);
}else
{
return -1;
}
}
public synchronized TCPFlow getTCPFlow(int flowID)
{
if( this.tcpFlowAllocated.containsKey(flowID) )
{
return this.tcpFlowAllocated.get(flowID);
}else
{
return null;
}
}
public synchronized boolean hasTCPFlow(String name)
{
return this.nameToFlowID.containsKey(name);
}
public synchronized int generateFlowId()
{
int flowID = -1;
flowID = (int)( Math.random()* (double)flowIDRange);
while(this.tcpFlowAllocated.containsKey(flowID) )
{
flowID = (int)( Math.random()* (double)flowIDRange);
}
return flowID;
}
public synchronized void addWireListener(int wireID, WireListenerTCP wireListener)
{
this.wireListeners.put(wireID, wireListener);
this.log.info("WireListener attached for TCP flow(wire): " + wireID);
}
public synchronized void removeWireListener(int wireID)
{
this.wireListeners.get(wireID).close();
this.wireListeners.remove(wireID);
this.log.info("WireListener removed for TCP flow(wire): " + wireID);
}
public synchronized int addDIF0FlowOnWire(int wireID, HandleEntry he)
{
return this.wireListeners.get(wireID).addDIF0Flow(he);
}
public synchronized void removeDIF0FlowOnWire(int wireID, HandleEntry he) {
this.wireListeners.get(wireID).removeDIF0Flow(he.getSrcPortID());
}
public synchronized void send(int flowID, byte[] msg) throws Exception {
this.tcpFlowAllocated.get(flowID).send(msg);
}
public byte[] receive(int wireID, int portID) {
return this.wireListeners.get(wireID).receive(portID);
}
public byte[] receive(int flowID) {
return this.tcpFlowMsgQueue.get(flowID).getReceive();
}
public synchronized LinkedHashMap<Integer, MessageQueue> getTcpFlowMsgQueue() {
return tcpFlowMsgQueue;
}
public synchronized void setTcpFlowMsgQueue(
LinkedHashMap<Integer, MessageQueue> tcpFlowMsgQueue) {
this.tcpFlowMsgQueue = tcpFlowMsgQueue;
}
public synchronized String getApName() {
return ApName;
}
public synchronized void setApName(String apName) {
ApName = apName;
}
public synchronized String getApInstance() {
return ApInstance;
}
public synchronized void setApInstance(String apInstance) {
ApInstance = apInstance;
}
public synchronized WellKnownRINAAddr getWellKnownRINAAddr() {
return wellKnownRINAAddr;
}
public synchronized void setWellKnownRINAAddr(
WellKnownRINAAddr wellKnownRINAAddr) {
this.wellKnownRINAAddr = wellKnownRINAAddr;
}
public synchronized RIBImpl getRib() {
return rib;
}
}