Expanded CMTS emulator to respond properly to gate add requests.
[packetcable.git] / packetcable-driver / src / main / java / org / pcmm / rcd / impl / CMTS.java
index 4a89bad0e0733d9a740dc43778746299db1a80a8..1c9f29cd3eca1dc1128e9deef4e0a0a6a5b7dadf 100644 (file)
-/**
- @header@
+/*
+ * (c) 2015 Cable Television Laboratories, Inc.  All rights reserved.
  */
+
 package org.pcmm.rcd.impl;
 
-import org.pcmm.gates.IPCMMGate;
-import org.pcmm.gates.ITransactionID;
-import org.pcmm.gates.impl.PCMMGateReq;
-import org.pcmm.messages.impl.MessageFactory;
+import org.pcmm.PCMMConstants;
+import org.pcmm.PCMMProperties;
+import org.pcmm.gates.IGateSpec.Direction;
 import org.pcmm.rcd.ICMTS;
-import org.umu.cops.COPSStateMan;
-import org.umu.cops.prpep.COPSPepConnection;
-import org.umu.cops.prpep.COPSPepDataProcess;
-import org.umu.cops.prpep.COPSPepException;
-import org.umu.cops.prpep.COPSPepReqStateMan;
-import org.umu.cops.stack.*;
-import org.umu.cops.stack.COPSHeader.OPCode;
 
+import java.io.IOException;
 import java.net.Socket;
 import java.util.*;
-import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This class starts a mock CMTS that can be used for testing.
  */
 public class CMTS extends AbstractPCMMServer implements ICMTS {
 
+       /**
+        * Receives messages from the COPS client
+        */
+       private final Map<String, IPCMMClientHandler> handlerMap;
+
+       /**
+        * The configured gates
+        */
+       private final Map<Direction, Set<String>> gateConfig;
+
+       /**
+        * The connected CMTSs and whether or not they are up
+        */
+       private final Map<String, Boolean> cmStatus;
+
        /**
         * Constructor for having the server port automatically assigned
         * Call getPort() after startServer() is called to determine the port number of the server
         */
-       public CMTS() {
-               this(0);
+       public CMTS(final Map<Direction, Set<String>> gateConfig, final Map<String, Boolean> cmStatus) {
+               this(0, gateConfig, cmStatus);
        }
 
        /**
         * Constructor for starting the server to a pre-defined port number
         * @param port - the port number on which to start the server.
         */
-       public CMTS(final int port) {
+       public CMTS(final int port, final Map<Direction, Set<String>> gateConfig, final Map<String, Boolean> cmStatus) {
                super(port);
+               if (gateConfig == null || cmStatus == null) throw new IllegalArgumentException("Config must not be null");
+               this.gateConfig = Collections.unmodifiableMap(gateConfig);
+               this.cmStatus = Collections.unmodifiableMap(cmStatus);
+               handlerMap = new ConcurrentHashMap<>();
        }
 
        @Override
-       protected IPCMMClientHandler getPCMMClientHandler(final Socket socket) {
-
-               return new AbstractPCMMClientHandler(socket) {
-
-                       private COPSHandle handle;
-
-                       public void run() {
-                               try {
-                                       // send OPN message
-                                       // set the major version info and minor version info to
-                                       // default (5,0)
-                                       logger.info("Send OPN message to the PS");
-                                       sendRequest(MessageFactory.getInstance().create(OPCode.OPN, new Properties()));
-                                       // wait for CAT
-                                       COPSMsg recvMsg = readMessage();
-
-                                       if (recvMsg.getHeader().getOpCode().equals(OPCode.CC)) {
-                                               COPSClientCloseMsg cMsg = (COPSClientCloseMsg) recvMsg;
-                                               logger.info("PS requested Client-Close" + cMsg.getError().getDescription());
-                                               // send a CC message and close the socket
-                                               disconnect();
-                                               return;
-                                       }
-                                       if (recvMsg.getHeader().getOpCode().equals(OPCode.CAT)) {
-                                               logger.info("received Client-Accept from PS");
-                                               COPSClientAcceptMsg cMsg = (COPSClientAcceptMsg) recvMsg;
-                                               // Support
-                                               if (cMsg.getIntegrity() != null) {
-                                                       throw new COPSPepException("Unsupported object (Integrity)");
-                                               }
-
-                                               // Mandatory KATimer
-                                               COPSKATimer kt = cMsg.getKATimer();
-                                               if (kt == null)
-                                                       throw new COPSPepException("Mandatory COPS object missing (KA Timer)");
-                                               short kaTimeVal = kt.getTimerVal();
-
-                                               // ACTimer
-                                               COPSAcctTimer at = cMsg.getAcctTimer();
-                                               short acctTimer = 0;
-                                               if (at != null)
-                                                       acctTimer = at.getTimerVal();
-
-                                               logger.info("Send a REQ message to the PS");
-                                               {
-                                                       Properties prop = new Properties();
-                                                       COPSMsg reqMsg = MessageFactory.getInstance().create(OPCode.REQ, prop);
-                                                       handle = ((COPSReqMsg) reqMsg).getClientHandle();
-                                                       sendRequest(reqMsg);
-                                               }
-                                               // Create the connection manager
-                                               final PCMMCmtsConnection conn = new PCMMCmtsConnection(CLIENT_TYPE, socket);
-                                               // pcmm specific handler
-                                               // conn.addReqStateMgr(handle, new
-                                               // PCMMPSReqStateMan(CLIENT_TYPE, handle));
-                                               conn.addRequestState(handle, new CmtsDataProcessor());
-                                               conn.setKaTimer(kaTimeVal);
-                                               conn.setAcctTimer(acctTimer);
-                                               logger.info(getClass().getName() + " Thread(conn).start");
-                                               new Thread(conn).start();
-                                       } else {
-                                               // messages of other types are not expected
-                                               throw new COPSPepException("Message not expected. Closing connection for " + socket.toString());
-                                       }
-                               } catch (Exception e) {
-                                       logger.error(e.getMessage());
-                               }
-                       }
-
-                       @Override
-                       public void task(Callable<?> c) {
-                               // TODO Auto-generated method stub
-
-                       }
-
-                       @Override
-                       public void shouldWait(int t) {
-                               // TODO Auto-generated method stub
-
-                       }
-
-                       @Override
-                       public void done() {
-                               // TODO Auto-generated method stub
-
-                       }
-
-               };
-       }
-
-       class PCMMCmtsConnection extends COPSPepConnection {
-
-               public PCMMCmtsConnection(final short clientType, final Socket sock) {
-                       super(clientType, sock);
-               }
-
-               public COPSPepReqStateMan addRequestState(final COPSHandle clientHandle, final COPSPepDataProcess process)
-                               throws COPSException {
-                       return super.addRequestState(clientHandle, process);
+       public void stopServer() {
+               for (final IPCMMClientHandler handler : handlerMap.values()) {
+                       handler.stop();
                }
+               super.stopServer();
        }
 
-       class CmtsDataProcessor implements COPSPepDataProcess {
-
-               private Map<String, String> removeDecs;
-               private Map<String, String> installDecs;
-               private Map<String, String> errorDecs;
-               private COPSPepReqStateMan stateManager;
-
-               public CmtsDataProcessor() {
-                       setRemoveDecs(new HashMap<String, String>());
-                       setInstallDecs(new HashMap<String, String>());
-                       setErrorDecs(new HashMap<String, String>());
-               }
-
-               @Override
-               public void setDecisions(final COPSPepReqStateMan man, final Map<String, String> removeDecs,
-                                 final Map<String, String> installDecs, final Map<String, String> errorDecs) {
-                       setRemoveDecs(removeDecs);
-                       setInstallDecs(installDecs);
-                       setErrorDecs(errorDecs);
-                       setStateManager(man);
-               }
-
-               @Override
-               public boolean isFailReport(final COPSPepReqStateMan man) {
-                       return (errorDecs != null && errorDecs.size() > 0);
-               }
-
-               @Override
-               public Map<String, String> getReportData(final COPSPepReqStateMan man) {
-                       if (isFailReport(man)) {
-                               return errorDecs;
-                       } else {
-                               final Map<String, String> siDataHashTable = new HashMap<>();
-                               if (installDecs.size() > 0) {
-                                       String data = "";
-                                       for (String k : installDecs.keySet()) {
-                                               data = installDecs.get(k);
-                                               break;
-                                       }
-                                       final ITransactionID transactionID = new PCMMGateReq(new COPSData(data).getData()).getTransactionID();
-                                       final IPCMMGate responseGate = new PCMMGateReq();
-                                       responseGate.setTransactionID(transactionID);
-
-                    // TODO FIXME - Why is the key always null??? What value should be used here???
-                    final String key = null;
-                                       siDataHashTable.put(key, new String(responseGate.getData()));
-                               }
-                               return siDataHashTable;
-                       }
-               }
-
-               @Override
-               public Map<String, String> getClientData(COPSPepReqStateMan man) {
-                       // TODO Auto-generated method stub
-                       return new HashMap<>();
-               }
-
-               @Override
-               public Map<String, String> getAcctData(COPSPepReqStateMan man) {
-                       // TODO Auto-generated method stub
-                       return new HashMap<>();
-               }
-
-               @Override
-               public void notifyClosedConnection(final COPSStateMan man, final COPSError error) {
-                       // TODO Auto-generated method stub
-               }
-
-               @Override
-               public void notifyNoKAliveReceived(final COPSStateMan man) {
-                       // TODO Auto-generated method stub
-               }
-
-               @Override
-               public void closeRequestState(final COPSStateMan man) {
-                       // TODO Auto-generated method stub
-               }
-
-               @Override
-               public void newRequestState(final COPSPepReqStateMan man) {
-                       // TODO Auto-generated method stub
-               }
-
-               public Map<String, String> getRemoveDecs() {
-                       return new HashMap<>(removeDecs);
-               }
-
-               public void setRemoveDecs(final Map<String, String> removeDecs) {
-                       this.removeDecs = new HashMap<>(removeDecs);
-               }
-
-               public Map<String, String> getInstallDecs() {
-                       return new HashMap<>(installDecs);
-               }
-
-               public void setInstallDecs(final Map<String, String> installDecs) {
-                       this.installDecs = new HashMap<>(installDecs);
-               }
-
-               public Map<String, String> getErrorDecs() {
-                       return errorDecs;
-               }
-
-               public void setErrorDecs(final Map<String, String> errorDecs) {
-                       this.errorDecs = new HashMap<>(errorDecs);
-               }
-
-               public COPSPepReqStateMan getStateManager() {
-                       return stateManager;
-               }
-
-               public void setStateManager(COPSPepReqStateMan stateManager) {
-                       this.stateManager = stateManager;
-               }
+       @Override
+       protected IPCMMClientHandler getPCMMClientHandler(final Socket socket) throws IOException {
+               final String key = socket.getLocalAddress().getHostName() + ':' + socket.getPort();
+               if (handlerMap.get(key) == null) {
+                       final IPCMMClientHandler handler = new CmtsPcmmClientHandler(socket, gateConfig, cmStatus);
+                       handler.connect();
+                       handlerMap.put(key, handler);
+                       return handler;
+               } else return handlerMap.get(key);
+       }
 
+       /**
+        * To start a CMTS
+        * @param args - the arguments which will contain configuration information
+        * @throws IOException - should the server fail to start for reasons such as port contention.
+        */
+       public static void main(final String[] args) throws IOException {
+               final CMTS cmts = new CMTS(PCMMProperties.get(PCMMConstants.PCMM_PORT, Integer.class),
+                               new HashMap<Direction, Set<String>>(), new HashMap<String, Boolean>());
+               cmts.startServer();
        }
+
 }