return new AbstractPCMMClientHandler(socket) {
- private String handle;
+ private COPSHandle handle;
public void run() {
try {
{
Properties prop = new Properties();
COPSMsg reqMsg = MessageFactory.getInstance().create(OPCode.REQ, prop);
- handle = ((COPSReqMsg) reqMsg).getClientHandle().getId().str();
+ handle = ((COPSReqMsg) reqMsg).getClientHandle();
sendRequest(reqMsg);
}
// Create the connection manager
- PCMMCmtsConnection conn = new PCMMCmtsConnection(CLIENT_TYPE, socket);
+ final PCMMCmtsConnection conn = new PCMMCmtsConnection(CLIENT_TYPE, socket);
// pcmm specific handler
// conn.addReqStateMgr(handle, new
// PCMMPSReqStateMan(CLIENT_TYPE, handle));
super(clientType, sock);
}
- public COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process)
- throws COPSException, COPSPepException {
+ public COPSPepReqStateMan addRequestState(final COPSHandle clientHandle, final COPSPepDataProcess process)
+ throws COPSException {
return super.addRequestState(clientHandle, process);
}
@SuppressWarnings("rawtypes")
class PCMMPSReqStateMan extends COPSPepReqStateMan {
- public PCMMPSReqStateMan(final short clientType, final String clientHandle) {
+ public PCMMPSReqStateMan(final short clientType, final COPSHandle clientHandle) {
super(clientType, clientHandle);
_process = new CmtsDataProcessor();
}
@Override
- protected void processDecision(COPSDecisionMsg dMsg)
- throws COPSPepException {
-
- // COPSHandle handle = dMsg.getClientHandle();
- Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
-
- Map<String, String> removeDecs = new HashMap<>();
- Map<String, String> installDecs = new HashMap<>();
- Map<String, String> errorDecs = new HashMap<>();
+ protected void processDecision(final COPSDecisionMsg dMsg, final Socket socket) throws COPSPepException {
+ final Map<String, String> removeDecs = new HashMap<>();
+ final Map<String, String> installDecs = new HashMap<>();
+ final Map<String, String> errorDecs = new HashMap<>();
for (final Set<COPSDecision> copsDecisions : dMsg.getDecisions().values()) {
final COPSDecision cmddecision = copsDecisions.iterator().next();
switch (cmddecision.getCommand()) {
case INSTALL:
for (final COPSDecision decision : copsDecisions) {
- COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+ final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
switch (obj.getSNum()) {
// TODO when there is install request only the PR_PRID
// is git but the ClientSI object containing the PR_EPD
}
case REMOVE:
for (final COPSDecision decision : copsDecisions) {
- COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+ final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
switch (obj.getSNum()) {
// TODO when there is install request only the PR_PRID
// is git but the ClientSI object containing the PR_EPD
}
@Override
- public boolean isFailReport(COPSPepReqStateMan man) {
+ public boolean isFailReport(final COPSPepReqStateMan man) {
return (errorDecs != null && errorDecs.size() > 0);
}
@Override
- public Map<String, String> getReportData(COPSPepReqStateMan man) {
+ public Map<String, String> getReportData(final COPSPepReqStateMan man) {
if (isFailReport(man)) {
return errorDecs;
} else {
- Map<String, String> siDataHashTable = new HashMap<>();
+ final Map<String, String> siDataHashTable = new HashMap<>();
if (installDecs.size() > 0) {
String data = "";
for (String k : installDecs.keySet()) {
break;
}
final ITransactionID transactionID = new PCMMGateReq(new COPSData(data).getData()).getTransactionID();
- IPCMMGate responseGate = new PCMMGateReq();
+ final IPCMMGate responseGate = new PCMMGateReq();
responseGate.setTransactionID(transactionID);
// TODO FIXME - Why is the key always null??? What value should be used here???
}
@Override
- public Hashtable getClientData(COPSPepReqStateMan man) {
+ public Map<String, String> getClientData(COPSPepReqStateMan man) {
// TODO Auto-generated method stub
- return new Hashtable<String, String>();
+ return new HashMap<>();
}
@Override
- public Hashtable getAcctData(COPSPepReqStateMan man) {
+ public Map<String, String> getAcctData(COPSPepReqStateMan man) {
// TODO Auto-generated method stub
- return new Hashtable<String, String>();
+ return new HashMap<>();
}
@Override
package org.umu.cops.prpep;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.umu.cops.stack.*;
import org.umu.cops.stack.COPSHeader.OPCode;
*/
public class COPSPepAgent {
+ private final static Logger logger = LoggerFactory.getLogger(COPSPepAgent.class);
+
/**
PEP's Identifier
*/
* @throws COPSException
* @throws COPSPepException
*/
- public boolean connect(String psHost, int psPort) throws IOException, COPSException, COPSPepException {
-
- // COPSDebug.out(getClass().getName(), "Thread ( " + _pepID + ") - Connecting to PDP");
+ public boolean connect(String psHost, int psPort) throws IOException, COPSException {
+ logger.info("Thread ( " + _pepID + ") - Connecting to PDP");
_psHost = psHost;
_psPort = psPort;
* @throws COPSPepException
* @throws COPSException
*/
- public COPSPepReqStateMan addRequestState(final String handle, final COPSPepDataProcess process)
- throws COPSPepException, COPSException {
+ public COPSPepReqStateMan addRequestState(final COPSHandle handle, final COPSPepDataProcess process)
+ throws COPSException {
if (_conn != null) {
return _conn.addRequestState(handle, process);
}
* @throws COPSPepException
* @throws COPSException
*/
- public void deleteRequestState(final COPSPepReqStateMan man)
- throws COPSPepException, COPSException {
+ public void deleteRequestState(final COPSPepReqStateMan man) throws COPSException {
if (_conn != null)
_conn.deleteRequestState(man);
}
* @throws COPSPepException
*
*/
- private COPSPepConnection processConnection(String psHost, int psPort)
- throws IOException, COPSException, COPSPepException {
+ private COPSPepConnection processConnection(final String psHost, final int psPort)
+ throws IOException, COPSException {
// Build OPN
final COPSClientOpenMsg msg = new COPSClientOpenMsg(_clientType, new COPSPepId(new COPSData(_pepID)),
null, null, null);
*/
public class COPSPepConnection implements Runnable {
- public final static Logger logger = LoggerFactory.getLogger(COPSPepConnection.class);
+ private final static Logger logger = LoggerFactory.getLogger(COPSPepConnection.class);
/** Socket connected to PDP */
protected Socket _sock;
/**
Maps a COPS Client Handle to a Request State Manager
*/
- protected final Map<String, COPSPepReqStateMan> _managerMap;
+ protected final Map<COPSHandle, COPSPepReqStateMan> _managerMap;
/**
COPS error returned by PDP
* @param sock Socket connected to PDP
*/
public COPSPepConnection(final short clientType, final Socket sock) {
-
_clientType = clientType;
_sock = sock;
* @throws COPSException
* @throws IOException
*/
- protected byte processMessage(final Socket conn) throws COPSPepException, COPSException, IOException {
+ protected byte processMessage(final Socket conn) throws COPSException, IOException {
final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
switch (msg.getHeader().getOpCode()) {
case CC:
- handleClientCloseMsg(conn, msg);
+ handleClientCloseMsg(conn, (COPSClientCloseMsg)msg);
return (byte)OPCode.CC.ordinal();
case DEC:
- handleDecisionMsg(conn, msg);
+ handleDecisionMsg((COPSDecisionMsg)msg);
return (byte)OPCode.DEC.ordinal();
case SSQ:
- handleSyncStateReqMsg(conn, msg);
+ handleSyncStateReqMsg((COPSSyncStateMsg)msg);
return (byte)OPCode.SSQ.ordinal();
case KA:
- handleKeepAliveMsg(conn, msg);
+ handleKeepAliveMsg((COPSKAMsg)msg);
return (byte)OPCode.KA.ordinal();
default:
throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");
/**
* Handle Client Close Message, close the passed connection
- *
* @param conn a Socket
- * @param msg a COPSMsg
- *
- *
- * <Client-Close> ::= <Common Header>
- * <Error>
- * [<Integrity>]
- *
- * Not support [<Integrity>]
- *
+ * @param cMsg a COPSClientCloseMsg
*/
- private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
- COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
+ private void handleClientCloseMsg(final Socket conn, final COPSClientCloseMsg cMsg) {
_error = cMsg.getError();
-
- // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
- // conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
-
+ logger.info("Got close request, closing connection "
+ + conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
try {
// Support
if (cMsg.getIntegrity() != null) {
logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
}
-
conn.close();
} catch (Exception unae) {
logger.error("Unexpected exception closing connection", unae);
/**
* Method getError
- *
* @return a COPSError
- *
*/
protected COPSError getError() {
return _error;
/**
* Handle Keep Alive Message
- *
- * <Keep-Alive> ::= <Common Header>
- * [<Integrity>]
- *
- * Not support [<Integrity>]
- *
- * @param conn a Socket
- * @param msg a COPSMsg
- *
+ * @param cMsg a COPSKAMsg
*/
- private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
- COPSKAMsg cMsg = (COPSKAMsg) msg;
-
- // COPSDebug.out(getClass().getName(),"Get KAlive Msg");
-
+ private void handleKeepAliveMsg(final COPSKAMsg cMsg) {
+ logger.info("Get KAlive Msg");
try {
// Support
if (cMsg.getIntegrity() != null) {
- logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+ logger.warn("Unsupported objects (Integrity)");
}
// should we do anything else?? ....
/**
* Method handleDecisionMsg
- *
- * <Decision Message> ::= <Common Header: Flag SOLICITED>
- * <Client Handle>
- * *(<Decision>) | <Error>
- * [<Integrity>]
- * <Decision> ::= <Context>
- * <Decision: Flags>
- * [<Named Decision Data: Provisioning>]
- * <Decision: Flags> ::= <Command-Code> NULLFlag
- * <Command-Code> ::= NULLDecision | Install | Remove
- * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>
- * <Install Decision> ::= *(<PRID> <EPD>)
- * <Remove Decision> ::= *(<PRID> | <PPRID>)
- *
- * Very important, this is actually being treated like this:
- * <Install Decision> ::= <PRID> | <EPD>
- * <Remove Decision> ::= <PRID> | <PPRID>
- *
- * @param conn a Socket
- * @param msg a COPSMsg
- *
+ * @param dMsg a COPSDecisionMsg
*/
- private void handleDecisionMsg(final Socket conn, final COPSMsg msg) throws COPSPepException {
- final COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
+ private void handleDecisionMsg(final COPSDecisionMsg dMsg) throws COPSPepException {
final COPSHandle handle = dMsg.getClientHandle();
final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
for (final Set<COPSDecision> copsDecisions: decisions.values()) {
for (final COPSDecision decision : copsDecisions) {
// Get the associated manager
- final COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
- if (manager == null)
- logger.warn("Unable to find state manager with key - " + handle.getId().str());
+ final COPSPepReqStateMan manager = _managerMap.get(handle);
+ if (manager == null) {
+ logger.warn("Unable to find state manager with key - " + handle);
+ return;
+ }
// Check message type
// TODO FIXME - Use of manager object could result in a NPE
manager.processDeleteRequestState(dMsg);
else
// Open new Request State
- handleOpenNewRequestStateMsg(conn, handle);
+ handleOpenNewRequestStateMsg(handle);
} else
// Decision
- manager.processDecision(dMsg);
+ manager.processDecision(dMsg, _sock);
}
}
}
/**
* Method handleOpenNewRequestStateMsg
- *
- * @param conn a Socket
* @param handle a COPSHandle
- *
*/
- private void handleOpenNewRequestStateMsg(Socket conn, COPSHandle handle) throws COPSPepException {
-
- COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
+ private void handleOpenNewRequestStateMsg(final COPSHandle handle) throws COPSPepException {
+ final COPSPepReqStateMan manager = _managerMap.get(handle);
if (manager == null)
logger.warn("Unable to find state manager with key - " + handle.getId().str());
-
- // TODO FIXME - Use of manager object could result in a NPE
- manager.processOpenNewRequestState();
+ else
+ manager.processOpenNewRequestState();
}
/**
* Method handleSyncStateReqMsg
- *
- * <Synchronize State> ::= <Common Header>
- * [<Client Handle>]
- * [<Integrity>]
- *
- * @param conn a Socket
- * @param msg a COPSMsg
- *
+ * @param cMsg a COPSSyncStateMsg
*/
- private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {
- COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
-
- // Support
+ private void handleSyncStateReqMsg(final COPSSyncStateMsg cMsg) throws COPSPepException {
if (cMsg.getIntegrity() != null) {
- logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+ logger.warn("Unsupported objects (Integrity)");
}
- COPSPepReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
- if (manager == null) {
+ final COPSPepReqStateMan manager = _managerMap.get(cMsg.getClientHandle());
+ if (manager == null)
logger.warn("Unable to find state manager with key - " + cMsg.getClientHandle().getId().str());
- } else {
+ else
manager.processSyncStateRequest(cMsg);
- }
}
/**
* Method createRequestState
- *
* @param clientHandle a String
* @param process a COPSPepDataProcess
- *
* @return a COPSPepmanager
- *
* @throws COPSException
* @throws COPSPepException
- *
*/
- protected COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process) throws COPSException,
- COPSPepException {
- COPSPepReqStateMan manager = new COPSPepReqStateMan(_clientType, clientHandle);
+ protected COPSPepReqStateMan addRequestState(final COPSHandle clientHandle, final COPSPepDataProcess process)
+ throws COPSException {
+ final COPSPepReqStateMan manager = new COPSPepReqStateMan(_clientType, clientHandle);
if (_managerMap.get(clientHandle) != null)
throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);
manager.setDataProcess(process);
- _managerMap.put(clientHandle,manager);
+ _managerMap.put(clientHandle, manager);
+ logger.info("Added state manager with key - " + clientHandle);
manager.initRequestState(_sock);
return manager;
}
/**
* Method deleteRequestState
- *
* @param manager a COPSPepReqStateMan
- *
* @throws COPSException
* @throws COPSPepException
- *
*/
- protected void deleteRequestState(COPSPepReqStateMan manager) throws COPSException, COPSPepException {
+ protected void deleteRequestState(COPSPepReqStateMan manager) throws COPSException {
manager.finalizeRequestState();
}
package org.umu.cops.prpep;
+import org.pcmm.gates.impl.GateID;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+import org.umu.cops.stack.COPSReportType.ReportType;
+import java.io.IOException;
import java.net.Socket;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
/**
* COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
*/
public class COPSPepReqStateMan {
+ // TODO - place these values into an enumeration
/**
* Request State created
*/
*/
public final static short ST_ACCT = 12;
+ private final static Logger logger = LoggerFactory.getLogger(COPSPepReqStateMan.class);
+
/**
* The client-type identifies the policy client
*/
* @param clientHandle a Client Handle
*
*/
- public COPSPepReqStateMan(final short clientType, final String clientHandle) {
- _handle = new COPSHandle(new COPSData(clientHandle));
+ public COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle) {
+ _handle = clientHandle;
_clientType = clientType;
_syncState = true;
_status = ST_CREATE;
* @param process a PolicyConfigure
*
*/
- public void setDataProcess(COPSPepDataProcess process) {
+ public void setDataProcess(final COPSPepDataProcess process) {
_process = process;
}
* @throws COPSPepException
*
*/
- protected void initRequestState(Socket sock)
- throws COPSPepException {
+ protected void initRequestState(final Socket sock) throws COPSPepException {
// Inits an object for sending COPS messages to the PDP
_sender = new COPSPepMsgSender(_clientType, _handle, sock);
* @throws COPSPepException
*
*/
- protected void finalizeRequestState()
- throws COPSPepException {
+ protected void finalizeRequestState() throws COPSPepException {
_sender.sendDeleteRequest();
_status = ST_FINAL;
}
* @throws COPSPepException
*
*/
- protected void processDecision(COPSDecisionMsg dMsg)
- throws COPSPepException {
- // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());
-
- // COPSHandle handle = dMsg.getClientHandle();
+ protected void processDecision(final COPSDecisionMsg dMsg, final Socket socket) throws COPSPepException {
+ logger.info("Processing decision message - " + dMsg);
final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
final Map<String, String> removeDecs = new HashMap<>();
final Map<String, String> installDecs = new HashMap<>();
- for (Set<COPSDecision> copsDecisions: decisions.values()) {
+ for (final Set<COPSDecision> copsDecisions: decisions.values()) {
final COPSDecision cmddecision = copsDecisions.iterator().next();
String prid = "";
switch (cmddecision.getCommand()) {
case INSTALL:
+ // TODO - break up this block
for (final COPSDecision decision : copsDecisions) {
- final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
- switch (obj.getSNum()) {
- case COPSPrObjBase.PR_PRID:
- prid = obj.getData().str();
- break;
- case COPSPrObjBase.PR_EPD:
- installDecs.put(prid, obj.getData().str());
- break;
- default:
- break;
+ if (decision.getData().getData().length != 0) {
+ final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+ switch (obj.getSNum()) {
+ case COPSPrObjBase.PR_PRID:
+ prid = obj.getData().str();
+ break;
+ case COPSPrObjBase.PR_EPD:
+ installDecs.put(prid, obj.getData().str());
+ break;
+ }
+ }
+ if (decision.getFlag().equals(DecisionFlag.REQERROR)) {
+ // This is assuming a gate set right or wrong
+ if (dMsg.getDecisions().size() == 1 && dMsg.getDecSI() != null) {
+ final PCMMGateReq gateReq = new PCMMGateReq(dMsg.getDecSI().getData().getData());
+ // TODO - Check and/or Set state here
+ // Gate ADD gateReq.getTrafficProfile() != null
+ // Gate REMOVE gateReq.getTrafficProfile() == null
+// final String gateName = trafficProfile.getData().str();
+// final Direction gateDir = gateReq.getGateSpec().getDirection();
+ final boolean success = true;
+
+ // Set response
+ final List<Byte> data = new ArrayList<>();
+ for (final byte val : gateReq.getTransactionID().getAsBinaryArray())
+ data.add(val);
+ for (final byte val : gateReq.getAMID().getAsBinaryArray())
+ data.add(val);
+ for (final byte val : gateReq.getSubscriberID().getAsBinaryArray())
+ data.add(val);
+
+ // Assign a gate ID
+ final GateID gateID = new GateID();
+ gateID.setGateID(UUID.randomUUID().hashCode());
+ for (final byte val : gateID.getAsBinaryArray())
+ data.add(val);
+
+
+ final byte[] csiArr = new byte[data.size()];
+ for (int i = 0; i < data.size(); i++) {
+ csiArr[i] = data.get(i);
+ }
+ final COPSClientSI si = new COPSClientSI(CNum.CSI, CType.DEF, new COPSData(csiArr, 0, csiArr.length));
+
+ final COPSReportMsg reportMsg;
+ if (success) {
+ reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
+ new COPSReportType(ReportType.SUCCESS), si, null);
+ } else {
+ reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
+ new COPSReportType(ReportType.FAILURE), si, null);
+ }
+
+ try {
+ reportMsg.writeData(socket);
+ } catch (IOException e) {
+ throw new COPSPepException("Error writing gate set SUCCESS Report", e);
+ }
+ }
}
}
break;
* @throws COPSPepException
*
*/
- protected void processOpenNewRequestState()
- throws COPSPepException {
+ protected void processOpenNewRequestState() throws COPSPepException {
if (_process != null)
_process.newRequestState(this);
* @throws COPSPepException
*
*/
- protected void processDeleteRequestState(COPSDecisionMsg dMsg)
- throws COPSPepException {
+ protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
if (_process != null)
_process.closeRequestState(this);
* @throws COPSPepException
*
*/
- protected void processSyncStateRequest(COPSSyncStateMsg ssMsg)
- throws COPSPepException {
+ protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSPepException {
_syncState = false;
// If an object for retrieving PEP features exists,
// use it for retrieving them
_status = ST_SYNC;
}
- protected void processClosedConnection(COPSError error)
- throws COPSPepException {
+ protected void processClosedConnection(final COPSError error) throws COPSPepException {
if (_process != null)
_process.notifyClosedConnection(this, error);
_status = ST_CCONN;
}
- protected void processNoKAConnection()
- throws COPSPepException {
+ protected void processNoKAConnection() throws COPSPepException {
if (_process != null)
_process.notifyNoKAliveReceived(this);
_status = ST_NOKA;
}
- protected void processAcctReport()
- throws COPSPepException {
-
+ protected void processAcctReport() throws COPSPepException {
final Map<String, String> report;
if (_process != null) report = _process.getAcctData(this);
else report = new HashMap<>();
private final IpAddress ipAddr;
private final PortNumber portNum;
protected final CcapClient ccapClient;
- private Map<String, PCMMGateReq> gateRequests = Maps.newConcurrentMap();
+ protected Map<String, PCMMGateReq> gateRequests = Maps.newConcurrentMap();
private final short clientType;
}
}
- public Boolean sendGateDelete(final Ccaps ccap, final String gatePathStr) {
+ public Boolean sendGateDelete(final String gatePathStr) {
logger.info("sendGateDelete() - " + ccap);
// recover the original gate request
final PCMMGateReq gateReq = gateRequests.remove(gatePathStr);
}
}
+ /**
+ * Used to interface with a CCAP (including CMTSs)
+ */
protected class CcapClient {
public final PCMMPdpDataProcess pcmmProcess;
public final PCMMPdpAgent pcmmPdp;
- // TODO - Needs to be initialized in connect() method or removed altogether as usage seems to be creating a new
- // TODO - one each time is is used
- protected transient PCMMPdpMsgSender pcmmSender;
-
private final String ipv4;
private final Integer port;
+ // Needs to be initialized in connect() method else would be final
+ protected transient PCMMPdpMsgSender pcmmSender;
+
private transient Boolean isConnected = false;
private transient String errMessage = null;
+ /**
+ * Constructor
+ * @param ccapIp - the IP of the CCAP to manage
+ * @param portNum - the port number of the CCAP to manage
+ */
public CcapClient(final IpAddress ccapIp, final PortNumber portNum) {
ipv4 = ccapIp.getIpv4Address().getValue();
if (portNum != null) port = portNum.getValue();
pcmmPdp = new PCMMPdpAgent(clientType, ipv4, port, pcmmProcess);
}
+ /**
+ * Starts the connection to the CCAP
+ */
public void connect( ) {
logger.info("Attempting to connect to host: " + ipv4 + " port: " + port);
try {
pcmmPdp.connect();
// Cannot instantiate until after pcmmPdp.connect() is called as this is where the client handle is created
- // pcmmSender = new PCMMPdpMsgSender(PCMMDef.C_PCMM, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
+ pcmmSender = new PCMMPdpMsgSender(clientType, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
isConnected = true;
} catch (Exception e) {
public Boolean sendGateSet(final PCMMGateReq gateReq) {
logger.info("CcapClient: sendGateSet(): {}:{} => {}", ipv4, port, gateReq);
try {
- pcmmSender = new PCMMPdpMsgSender(clientType, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
pcmmSender.sendGateSet(gateReq);
+
// TODO - determine if this is the correct place to perform this operation as this currently is the
// TODO - place where the gate ID can be set on the gateReq object
// pcmmSender.handleGateReport(pcmmPdp.getSocket());
public Boolean sendGateDelete(final PCMMGateReq gateReq) {
logger.info("CcapClient: sendGateDelete(): {}:{} => {}", ipv4, port, gateReq);
try {
- pcmmSender = new PCMMPdpMsgSender(clientType, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
pcmmSender.sendGateDelete(gateReq);
} catch (COPSPdpException e) {
logger.error("CcapClient: sendGateDelete(): {}:{} => {} FAILED: {}", ipv4, port, gateReq, e.getMessage());
final AsyncReadWriteTransaction<InstanceIdentifier<?>, ?> tx = dataBroker.newReadWriteTransaction();
tx.delete(LogicalDatastoreType.CONFIGURATION, ccapIID);
tx.delete(LogicalDatastoreType.CONFIGURATION, qosIID);
+ // TODO - commit() below has been deprecated
tx.commit().get();
}
}
logger.info("onDataChanged().getCcaps(): " + thisData);
for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
if (entry.getValue() instanceof Ccaps) {
+ // TODO FIXME - Potential ClassCastException thrown here!!!
ccapIidMap.put((InstanceIdentifier<Ccaps>)entry.getKey(), (Ccaps)entry.getValue());
}
}
for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
if (entry.getValue() instanceof Gates) {
final Gates gate = (Gates)entry.getValue();
+
+ // TODO FIXME - Potential ClassCastException thrown here!!!
final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
getGatePathMap(gateIID);
gateIidMap.put(gateIID, gate);
logger.info("onDataChanged(): created CCAP: {}/{} : {}", thisData.gatePath, thisCcap, message);
logger.info("onDataChanged(): created CCAP: {} : {}", thisData.gatePath, message);
} else {
+ // TODO - when a connection cannot be made, need to remove CCAP from ODL cache.
logger.error("onDataChanged(): create CCAP Failed: {} : {}", thisData.gatePath, message);
}
// set the response string in the config ccap object using a new thread
final Ccaps thisCcap = ccapMap.get(ccapId);
final PCMMService service = pcmmServiceMap.get(thisCcap);
if (service != null) {
- service.sendGateDelete(thisCcap, gatePathStr);
+ service.sendGateDelete(gatePathStr);
logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr, thisGate);
logger.info("onDataChanged(): removed QoS gate {} for {}/{}: ", gateId, ccapId, gatePathStr);
} else
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TosByte;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TpProtocol;
import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmId;
import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.Connection;
import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gate.spec.GateSpec;
import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfile;
+import org.pcmm.gates.IPCMMGate;
import org.pcmm.rcd.IPCMMClient;
import org.pcmm.rcd.impl.CMTS;
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.net.InetAddress;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
/**
* Tests the PCMMService's ability to connect to a CMTS. Gate additions will not properly work as there is currently
* not any other means to receive acknowledgements. This functionality must be tested by the PCMMService's client
- * PacketcableProvider
+ * PacketcableProvider.
*/
public class PCMMServiceTest {
- private Ccaps ccap;
+ /**
+ * The mock CMTS running on localhost with a dynamic port assigned.
+ */
private CMTS icmts;
+ /**
+ * Represents the IP address of the CM the gate should be set against.
+ */
+ private byte[] cmAddr = new byte[4];
+
@Before
public void setup() {
icmts = new CMTS();
icmts.startServer();
- ccap = Mockito.mock(Ccaps.class);
- final Connection conn = Mockito.mock(Connection.class);
- Mockito.when(ccap.getConnection()).thenReturn(conn);
- final PortNumber port = Mockito.mock(PortNumber.class);
- Mockito.when(conn.getPort()).thenReturn(port);
- Mockito.when(port.getValue()).thenReturn(icmts.getPort());
- final IpAddress addr = Mockito.mock(IpAddress.class);
- Mockito.when(conn.getIpAddress()).thenReturn(addr);
- final Ipv4Address ipv4 = Mockito.mock(Ipv4Address.class);
- Mockito.when(addr.getIpv4Address()).thenReturn(ipv4);
-
- // Switch the value to a real CMTS here to test against it
- // Ensure the code is checked in with 127.0.0.1
- Mockito.when(ipv4.getValue()).thenReturn("127.0.0.1");
-
- // Following line has been commented out for testing against a real Arris CMTS in the Louisville development lab
-// Mockito.when(ipv4.getValue()).thenReturn("10.32.10.3");
-
- Mockito.when(ccap.getCcapId()).thenReturn("ccap-1");
- final AmId amid = Mockito.mock(AmId.class);
- Mockito.when(ccap.getAmId()).thenReturn(amid);
- Mockito.when(amid.getAmTag()).thenReturn(0xcada);
- Mockito.when(amid.getAmType()).thenReturn(1);
+ cmAddr[0] = 10;
+ cmAddr[1] = 32;
+ cmAddr[2] = 110;
+ cmAddr[3] = (byte)180;
}
@After
@Test
public void testAddCcap() {
+
+ // TODO - comment out for testing
+ // final Ipv4Address cmtsAddr = new Ipv4Address("10.32.10.3");
+// final Ccaps ccap = makeCcapsObj(PCMMPdpAgent.WELL_KNOWN_PDP_PORT, cmtsAddr.getValue(), "ccap-1");
+
+ // TODO - Use this instead for automated testing
+ final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
+ final Ccaps ccap = makeCcapsObj(icmts.getPort(), cmtsAddr.getValue(), "ccap-1");
+
final PCMMService service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
final String message = service.addCcap();
- Assert.assertTrue(message.startsWith("200"));
+ Assert.assertNotNull(message);
+ Assert.assertTrue(message, message.startsWith("200"));
Assert.assertNotNull(service.ccapClient.pcmmPdp.getClientHandle());
-
- // TODO - remove this sleep
-/*
- try {
- Thread.sleep(100000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-*/
+ service.disconect();
}
-// @Test
- public void testAddGate() throws Exception {
+ @Test
+ public void testAddAndRemoveUpGate() throws Exception {
+
+ // TODO - Use this block to test against a real CMTS
+// final Ipv4Address cmtsAddr = new Ipv4Address("10.32.10.3");
+// final Ccaps ccap = makeCcapsObj(PCMMPdpAgent.WELL_KNOWN_PDP_PORT, cmtsAddr.getValue(), "ccap-1");
+
+ // TODO - Use this block for automated testing
+ final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
+ final Ccaps ccap = makeCcapsObj(icmts.getPort(), cmtsAddr.getValue(), "ccap-1");
+
final PCMMService service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
service.addCcap();
- final byte[] addr = new byte[4];
- addr[0] = 10;
- addr[1] = 32;
- addr[2] = 110;
- addr[3] = (byte)180;
+ final Gates gate = makeGateObj("extrm_up", cmtsAddr, ServiceFlowDirection.Us);
+ final String gatePath = "testGatePath";
+
+ // Add gate
+ final String msg = service.sendGateSet(gatePath, InetAddress.getByAddress(cmAddr), gate,
+ ServiceFlowDirection.Us);
+ Assert.assertTrue(msg, msg.startsWith("200"));
+
+ // TODO - add validation to the PCMMGateReq contained within the map
+ Assert.assertEquals(1, service.gateRequests.size());
+
+ // Remove gate
+ service.sendGateDelete(gatePath);
+
+ // Wait up to 1 sec for response to be processed
+ final long start = System.currentTimeMillis();
+ while (1000 < System.currentTimeMillis() - start) {
+ if (service.gateRequests.size() == 0) break;
+ }
+ Assert.assertEquals(0, service.gateRequests.size());
+ service.disconect();
+ }
+
+ /**
+ * This tests the instantiation of a COPSDecisionMsg object that is responsible for setting a gate request,
+ * streams it over a mock Socket object and parses the bytes into a new COPSDecisionMsg object which should
+ * be equivalent
+ * @throws Exception - test will fail should any exception be thrown during execution
+ */
+ @Test
+ public void testGateRequestDecisionMsg() throws Exception {
+ final Socket socket = new MockSocket();
+ final Ccaps ccap = makeCcapsObj(icmts.getPort(), "127.0.0.1", "ccap-1");
+ final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
+ final Gates gate = makeGateObj("extrm_up", cmtsAddr, ServiceFlowDirection.Us);
+ final IPCMMGate gateReq = makeGateRequest(ccap, gate, InetAddress.getByName("localhost"),
+ ServiceFlowDirection.Us);
+ final byte[] data = gateReq.getData();
+
+ final Set<COPSDecision> decisionSet = new HashSet<>();
+ decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
+ final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+ decisionMap.put(new COPSContext(RType.CONFIG, (short) 0), decisionSet);
+
+ final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData("123")),
+ decisionMap, null, clientSD);
+ decisionMsg.writeData(socket);
+
+ final COPSMsg msg = COPSMsgParser.parseMessage(socket);
+ Assert.assertNotNull(msg);
+ Assert.assertEquals(decisionMsg, msg);
+ }
+
+ /**
+ * Creates a mock Ccaps object that can be used for connecting to a CMTS
+ * @param inPort - the CMTS port number
+ * @param ipAddr - the CMTS IPv4 address string
+ * @param ccapId - the ID of the CCAP
+ * @return - the mock Ccaps object
+ */
+ private Ccaps makeCcapsObj(final int inPort, final String ipAddr, final String ccapId) {
+ final Ccaps ccap = Mockito.mock(Ccaps.class);
+ final Connection conn = Mockito.mock(Connection.class);
+ Mockito.when(ccap.getConnection()).thenReturn(conn);
+ final PortNumber port = Mockito.mock(PortNumber.class);
+ Mockito.when(conn.getPort()).thenReturn(port);
+ Mockito.when(port.getValue()).thenReturn(inPort);
+
+ final IpAddress addr = Mockito.mock(IpAddress.class);
+ Mockito.when(conn.getIpAddress()).thenReturn(addr);
+ final Ipv4Address ipv4 = new Ipv4Address(ipAddr);
+ Mockito.when(addr.getIpv4Address()).thenReturn(ipv4);
+
+ Mockito.when(ccap.getCcapId()).thenReturn(ccapId);
+ final AmId amid = Mockito.mock(AmId.class);
+ Mockito.when(ccap.getAmId()).thenReturn(amid);
+ Mockito.when(amid.getAmTag()).thenReturn(0xcada);
+ Mockito.when(amid.getAmType()).thenReturn(1);
+
+ return ccap;
+ }
+
+ /**
+ * Creates a mock Gates object
+ * @param scnValue - the service class name defined on the CMTS
+ * @param dstAddr - the CM address this gate should be set against
+ * @return - the gate request
+ */
+ private Gates makeGateObj(final String scnValue, final Ipv4Address dstAddr, final ServiceFlowDirection direction) {
final Gates gate = Mockito.mock(Gates.class);
final GateSpec gateSpec = Mockito.mock(GateSpec.class);
Mockito.when(gate.getGateSpec()).thenReturn(gateSpec);
- Mockito.when(gateSpec.getDirection()).thenReturn(ServiceFlowDirection.Us);
+ Mockito.when(gateSpec.getDirection()).thenReturn(direction);
// TODO - make sure to write a test when this value is not null
Mockito.when(gateSpec.getDscpTosOverwrite()).thenReturn(null);
final TrafficProfile trafficProfile = Mockito.mock(TrafficProfile.class);
final ServiceClassName scn = Mockito.mock(ServiceClassName.class);
- Mockito.when(scn.getValue()).thenReturn("extrm_up");
+ Mockito.when(scn.getValue()).thenReturn(scnValue);
Mockito.when(trafficProfile.getServiceClassName()).thenReturn(scn);
Mockito.when(gate.getTrafficProfile()).thenReturn(trafficProfile);
// TODO - write tests when this is null and ExtClassifier or Ipv6Classifier objects are not null
final Classifier classifier = Mockito.mock(Classifier.class);
+
+ // This is the address of the CM
+ Mockito.when(classifier.getDstIp()).thenReturn(dstAddr);
+
+ final PortNumber dstPort = new PortNumber(4321);
+ Mockito.when(classifier.getDstPort()).thenReturn(dstPort);
+ final TpProtocol protocol = new TpProtocol(0);
+ Mockito.when(classifier.getProtocol()).thenReturn(protocol);
+ final Ipv4Address srcAddr = new Ipv4Address("127.0.0.1");
+ Mockito.when(classifier.getSrcIp()).thenReturn(srcAddr);
+ final PortNumber srcPort = new PortNumber(1234);
+ Mockito.when(classifier.getSrcPort()).thenReturn(srcPort);
+ final TosByte tosByte = new TosByte((short)160);
+ Mockito.when(classifier.getTosByte()).thenReturn(tosByte);
+ final TosByte tosMask = new TosByte((short)224);
+ Mockito.when(classifier.getTosMask()).thenReturn(tosMask);
+
+ // TODO - enhance to test support of the other classifier types
Mockito.when(gate.getClassifier()).thenReturn(classifier);
Mockito.when(gate.getExtClassifier()).thenReturn(null);
Mockito.when(gate.getIpv6Classifier()).thenReturn(null);
+ return gate;
+ }
- // TODO - remove this sleep
- Thread.sleep(1000);
+ private IPCMMGate makeGateRequest(final Ccaps ccap, final Gates gateReq, final InetAddress addrSubId,
+ final ServiceFlowDirection direction) {
+ final PCMMGateReqBuilder gateBuilder = new PCMMGateReqBuilder();
+ gateBuilder.build(ccap.getAmId());
+ gateBuilder.build(addrSubId);
+ // force gateSpec.Direction to align with SCN direction
+ final ServiceClassName scn = gateReq.getTrafficProfile().getServiceClassName();
+ if (scn != null) {
+ gateBuilder.build(gateReq.getGateSpec(), direction);
+ } else {
+ // not an SCN gate
+ gateBuilder.build(gateReq.getGateSpec(), null);
+ }
+ gateBuilder.build(gateReq.getTrafficProfile());
- final String msg = service.sendGateSet("app1/10.32.110.180/gate2", InetAddress.getByAddress(addr), gate,
- ServiceFlowDirection.Us);
- Assert.fail(msg);
+ // pick a classifier type (only one for now)
+ if (gateReq.getClassifier() != null) {
+ gateBuilder.build(gateReq.getClassifier());
+ } else if (gateReq.getExtClassifier() != null) {
+ gateBuilder.build(gateReq.getExtClassifier());
+ } else if (gateReq.getIpv6Classifier() != null) {
+ gateBuilder.build(gateReq.getIpv6Classifier());
+ }
+ // assemble the final gate request
+ return gateBuilder.getGateReq();
+ }
+
+ private class MockSocket extends Socket {
+
+ private ByteArrayOutputStream os = new ByteArrayOutputStream();
+ private ByteArrayInputStream is;
+
+ @Override
+ public OutputStream getOutputStream() {
+ return os;
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ if (is == null) is = new ByteArrayInputStream(os.toByteArray());
+ return is;
+ }
}
}