Moved all identical attributes and methods from COPSPdpConnection & COPSPepConnection...
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / prpdp / COPSPdpAgent.java
index be174403844701cc5d3c7803d58fd27ca90dfd18..eed74c90e3021818b75c1fc4974f0f63ed7037a3 100644 (file)
-/*\r
- * Copyright (c) 2004 University of Murcia.  All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpdp;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.umu.cops.stack.*;\r
-\r
-import java.io.IOException;\r
-import java.net.ServerSocket;\r
-import java.net.Socket;\r
-import java.util.Hashtable;\r
-import java.util.Map;\r
-import java.util.concurrent.ConcurrentHashMap;\r
-\r
-/**\r
- * Core PDP agent for provisioning\r
- */\r
-public class COPSPdpAgent extends Thread {\r
-\r
-    public final static Logger logger = LoggerFactory.getLogger(COPSPdpAgent.class);\r
-\r
-    /** Well-known port for COPS */\r
-    public static final int WELL_KNOWN_PDP_PORT = 3288;\r
-    /** Default keep-alive timer value (secs) */\r
-    public static final short KA_TIMER_VALUE = 30;\r
-    /** Default accounting timer value (secs) */\r
-    public static final short ACCT_TIMER_VALUE = 0;\r
-\r
-    /**\r
-        PDP host port\r
-     */\r
-    private int _serverPort;\r
-\r
-    /**\r
-        Client-type of connecting PEP\r
-     */\r
-    private short _clientType;\r
-\r
-    /**\r
-        Accounting timer (secs)\r
-     */\r
-    private short _acctTimer;\r
-\r
-    /**\r
-        Keep-alive timer (secs)\r
-     */\r
-    private short _kaTimer;\r
-\r
-    /**\r
-        Maps a PEP-ID to a connection\r
-     */\r
-    private final Map<String, COPSPdpConnection> _connectionMap;\r
-    // map < String(PEPID), COPSPdpConnection > ConnectionMap;\r
-\r
-    /**\r
-     *  Policy data processing object\r
-     */\r
-    private COPSPdpDataProcess _process;\r
-\r
-    /**\r
-     * Creates a PDP Agent\r
-     *\r
-     * @param clientType    COPS Client-type\r
-     * @param process       Object to perform policy data processing\r
-     */\r
-    public COPSPdpAgent(short clientType, COPSPdpDataProcess process) {\r
-        _serverPort = WELL_KNOWN_PDP_PORT;\r
-        _kaTimer = KA_TIMER_VALUE;\r
-        _acctTimer = ACCT_TIMER_VALUE;\r
-\r
-        _clientType = clientType;\r
-        _connectionMap = new ConcurrentHashMap<>();\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Creates a PDP Agent\r
-     *\r
-     * @param port  Port to listen to\r
-     * @param clientType    COPS Client-type\r
-     * @param process   Object to perform policy data processing\r
-     */\r
-    public COPSPdpAgent(int port, short clientType, COPSPdpDataProcess process) {\r
-        _serverPort = port;\r
-\r
-        _kaTimer = KA_TIMER_VALUE;\r
-        _acctTimer = ACCT_TIMER_VALUE;\r
-\r
-        _clientType = clientType;\r
-        _connectionMap = new ConcurrentHashMap<>();\r
-        _process = process;\r
-    }\r
-\r
-    /**\r
-     * Sets the keep-alive timer value\r
-     * @param    kaTimer    Keep alive timer value (secs)\r
-     */\r
-    public void setKaTimer (short kaTimer) {\r
-        _kaTimer = kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Sets the accounting timer value\r
-     * @param    acctTimer  Accounting timer value (secs)\r
-     */\r
-    public void setAcctTimer (short acctTimer) {\r
-        _acctTimer = acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the value of the keep-alive timer\r
-     * @return   Keep-alive timer value (secs)\r
-     */\r
-    public short getKaTimer () {\r
-        return _kaTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the accounting timer value\r
-     * @return   Accounting timer value (secs)\r
-     */\r
-    public short getAcctTimer () {\r
-        return _acctTimer;\r
-    }\r
-\r
-    /**\r
-     * Gets the connection map\r
-     * @return   A <tt>Hashtable</tt> holding the connection map\r
-     */\r
-    public Hashtable getConnectionMap() {\r
-        return new Hashtable(_connectionMap);\r
-    }\r
-\r
-    /**\r
-     * Gets the client-type\r
-     * @return   The client-type\r
-     */\r
-    public short getClientType() {\r
-        return _clientType;\r
-    }\r
-\r
-    /**\r
-     * Disconnects a PEP\r
-     * @param pepID PEP-ID of the PEP to be disconnected\r
-     * @param error COPS Error to be reported as a reason\r
-     * @throws COPSException\r
-     * @throws IOException\r
-     */\r
-    public void disconnect (String pepID, COPSError error)\r
-    throws COPSException, IOException {\r
-\r
-        COPSPdpConnection pdpConn = _connectionMap.get(pepID);\r
-\r
-        COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);\r
-        COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-        closeMsg.add(cHdr);\r
-        if (error != null)\r
-            closeMsg.add(error);\r
-\r
-        closeMsg.writeData(pdpConn.getSocket());\r
-        pdpConn.close();\r
-    }\r
-\r
-    /**\r
-     * Requests a COPS sync for a PEP\r
-     * @param pepID PEP-ID of the PEP to be synced\r
-     * @throws COPSException\r
-     * @throws COPSPdpException\r
-     */\r
-    public void sync (String pepID)\r
-    throws COPSException, COPSPdpException {\r
-\r
-        COPSPdpConnection pdpConn = _connectionMap.get(pepID);\r
-        pdpConn.syncAllRequestState();\r
-    }\r
-\r
-    /**\r
-     * Removes a PEP from the connection map\r
-     * @param pepID PEP-ID of the PEP to be removed\r
-     */\r
-    public void delete (String pepID) {\r
-        _connectionMap.remove(pepID);\r
-    }\r
-\r
-\r
-    /**\r
-     * Runs the PDP process\r
-     */\r
-    public void run() {\r
-        try {\r
-            final ServerSocket serverSocket = new ServerSocket (_serverPort);\r
-\r
-            //Loop through for Incoming messages\r
-\r
-            // server infinite loop\r
-            while (true) {\r
-\r
-                // Wait for an incoming connection from a PEP\r
-                Socket socket = serverSocket.accept();\r
-\r
-                // COPSDebug.out(getClass().getName(),"New connection accepted " +\r
-                //           socket.getInetAddress() +\r
-                //           ":" + socket.getPort());\r
-\r
-                // We're waiting for an OPN message\r
-                try {\r
-                    COPSMsg msg = COPSTransceiver.receiveMsg(socket);\r
-                    if (msg.getHeader().isAClientOpen()) {\r
-                        handleClientOpenMsg(socket, msg);\r
-                    } else {\r
-                        // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
-                        try {\r
-                            socket.close();\r
-                        } catch (Exception ex) {\r
-                            logger.error("Error closing socket", ex);\r
-                        }\r
-                    }\r
-                } catch (Exception e) { // COPSException, IOException\r
-                    // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,\r
-                    //    "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);\r
-                    try {\r
-                        socket.close();\r
-                    } catch (Exception ex) {\r
-                        logger.error("Error closing socket", ex);\r
-                    }\r
-                }\r
-            }\r
-        } catch (IOException e) {\r
-            logger.error("Error caught while processing socket messages", e);\r
-        }\r
-    }\r
-\r
-    /**\r
-      * Handles a COPS client-open message\r
-      * @param    conn Socket to the PEP\r
-      * @param    msg <tt>COPSMsg</tt> holding the client-open message\r
-      * @throws COPSException\r
-      * @throws IOException\r
-      */\r
-    private void handleClientOpenMsg(Socket conn, COPSMsg msg)\r
-    throws COPSException, IOException {\r
-        COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;\r
-        COPSPepId pepId = cMsg.getPepId();\r
-\r
-        // Validate Client Type\r
-        if (msg.getHeader().getClientType() != _clientType) {\r
-            // Unsupported client type\r
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
-            COPSError err = new COPSError(COPSError.COPS_ERR_UNSUPPORTED_CLIENT_TYPE, (short) 0);\r
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-            closeMsg.add(cHdr);\r
-            closeMsg.add(err);\r
-            try {\r
-                closeMsg.writeData(conn);\r
-            } catch (IOException unae) {\r
-                logger.error("Error writing COPS data", unae);\r
-            }\r
-\r
-            throw new COPSException("Unsupported client type");\r
-        }\r
-\r
-        // PEPId is mandatory\r
-        if (pepId == null) {\r
-            // Mandatory COPS object missing\r
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
-            COPSError err = new COPSError(COPSError.COPS_ERR_MANDATORY_OBJECT_MISSING, (short) 0);\r
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-            closeMsg.add(cHdr);\r
-            closeMsg.add(err);\r
-            try {\r
-                closeMsg.writeData(conn);\r
-            } catch (IOException unae) {\r
-                logger.error("Error writing close message", unae);\r
-            }\r
-\r
-            throw new COPSException("Mandatory COPS object missing (PEPId)");\r
-        }\r
-\r
-        // Support\r
-        if ( (cMsg.getClientSI() != null) ||\r
-                (cMsg.getPdpAddress() != null) ||\r
-                (cMsg.getIntegrity() != null)) {\r
-\r
-            // Unsupported objects\r
-            COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());\r
-            COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT, (short) 0);\r
-            COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();\r
-            closeMsg.add(cHdr);\r
-            closeMsg.add(err);\r
-            try {\r
-                closeMsg.writeData(conn);\r
-            } catch (IOException unae) {\r
-                logger.error("Error writing close message", unae);\r
-            }\r
-\r
-            throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");\r
-        }\r
-\r
-        // Connection accepted\r
-        COPSHeader ahdr = new COPSHeader(COPSHeader.COPS_OP_CAT, msg.getHeader().getClientType());\r
-        COPSKATimer katimer = new COPSKATimer(_kaTimer);\r
-        COPSAcctTimer acctTimer = new COPSAcctTimer(_acctTimer);\r
-        COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();\r
-        acceptMsg.add(ahdr);\r
-        acceptMsg.add(katimer) ;\r
-        if (_acctTimer != 0) acceptMsg.add(acctTimer);\r
-        acceptMsg.writeData(conn);\r
-\r
-        COPSPdpConnection pdpConn = new COPSPdpConnection(pepId,conn,_process);\r
-        pdpConn.setKaTimer(_kaTimer);\r
-        if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);\r
-        new Thread(pdpConn).start();\r
-        _connectionMap.put(pepId.getData().str(),pdpConn);\r
-    }\r
-\r
-}\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2004 University of Murcia.  All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpdp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSHeader.OPCode;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Core PDP agent for provisioning
+ */
+public class COPSPdpAgent extends Thread {
+
+    private static final Logger logger = LoggerFactory.getLogger(COPSPdpAgent.class);
+
+    /** Well-known port for COPS */
+    //    public static final int WELL_KNOWN_PDP_PORT = 3288;
+    /** Default keep-alive timer value (secs) */
+    public static final short KA_TIMER_VALUE = 30;
+    /** Default accounting timer value (secs) */
+    public static final short ACCT_TIMER_VALUE = 0;
+
+    /**
+     * PDP host port
+     */
+    private int _serverPort;
+
+    /**
+     * Client-type of connecting PEP
+     */
+    private short _clientType;
+
+    /**
+     * Accounting timer (secs)
+     */
+    private short _acctTimer;
+
+    /**
+     * Keep-alive timer (secs)
+     */
+    private short _kaTimer;
+
+    /**
+     * The PEP ID
+     */
+    protected transient COPSPepId _pepId;
+
+    /**
+     *   Maps a PEP-ID to a connection
+     *   TODO - Refactor COPSPdpConnection to extend PCMMPdpConnection. Until then, the value must remain an Object
+     */
+    protected Map<String, Object> _connectionMap;
+    // map < String(PEPID), COPSPdpConnection > ConnectionMap;
+
+    /**
+     *  Policy data processing object
+     */
+    private COPSPdpDataProcess _process;
+
+    /**
+     * Holds all of the threads to manage by PEP ID
+     */
+    protected final Map<String, Thread> threadMap;
+
+    /**
+     * Creates a PDP Agent
+     *
+     * @param port  Port to listen to
+     * @param clientType    COPS Client-type
+     * @param process   Object to perform policy data processing
+     */
+    public COPSPdpAgent(final int port, final short clientType, final COPSPdpDataProcess process) {
+        _serverPort = port;
+
+        _kaTimer = KA_TIMER_VALUE;
+        _acctTimer = ACCT_TIMER_VALUE;
+
+        _clientType = clientType;
+        _connectionMap = new ConcurrentHashMap<>();
+        _process = process;
+        this.threadMap = new ConcurrentHashMap<>();
+    }
+
+    /**
+     * Gets the value of the keep-alive timer
+     * @return   Keep-alive timer value (secs)
+     */
+    public short getKaTimer () {
+        return _kaTimer;
+    }
+
+    /**
+     * Gets the accounting timer value
+     * @return   Accounting timer value (secs)
+     */
+    public short getAcctTimer () {
+        return _acctTimer;
+    }
+
+    /**
+     * Gets the client-type
+     * @return   The client-type
+     */
+    public short getClientType() {
+        return _clientType;
+    }
+
+    /**
+     * Disconnects a PEP
+     * @param pepID PEP-ID of the PEP to be disconnected
+     * @param error COPS Error to be reported as a reason
+     * @throws COPSException
+     * @throws IOException
+     */
+    public void disconnect(final String pepID, final COPSError error) throws COPSException, IOException {
+        final COPSPdpConnection pdpConn = (COPSPdpConnection)_connectionMap.get(pepID);
+        final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
+        closeMsg.writeData(pdpConn.getSocket());
+        pdpConn.close();
+    }
+
+    /**
+     * Requests a COPS sync for a PEP
+     * @param pepID PEP-ID of the PEP to be synced
+     * @throws COPSException
+     * @throws COPSPdpException
+     */
+    public void sync(final String pepID) throws COPSException {
+        COPSPdpConnection pdpConn = (COPSPdpConnection) _connectionMap.get(pepID);
+        pdpConn.syncAllRequestState();
+    }
+
+    /**
+     * Removes a PEP from the connection map
+     * @param pepID PEP-ID of the PEP to be removed
+     */
+    public void delete(final String pepID) {
+        _connectionMap.remove(pepID);
+    }
+
+
+    /**
+     * Runs the PDP process
+     */
+    public void run() {
+        try {
+            final ServerSocket serverSocket = new ServerSocket (_serverPort);
+
+            //Loop through for Incoming messages
+            // server infinite loop
+            while (true) {
+                // Wait for an incoming connection from a PEP
+                final Socket socket = serverSocket.accept();
+
+                // COPSDebug.out(getClass().getName(),"New connection accepted " +
+                //           socket.getInetAddress() +
+                //           ":" + socket.getPort());
+
+                // We're waiting for an OPN message
+                try {
+                    final COPSMsg msg = COPSTransceiver.receiveMsg(socket);
+                    logger.info("Message received - " + msg);
+                    if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
+                        handleClientOpenMsg(socket, msg);
+                    } else {
+                        logger.error("Not an open message, closing socket");
+                        try {
+                            socket.close();
+                        } catch (Exception ex) {
+                            logger.error("Unexpected exception closing socket", ex);
+                        }
+                    }
+                } catch (Exception e) { // COPSException, IOException
+                    // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,
+                    //    "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);
+                    try {
+                        socket.close();
+                    } catch (Exception ex) {
+                        logger.error("Unexpected exception closing socket", ex);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            logger.error("Error caught while processing socket messages", e);
+        }
+    }
+
+    /**
+     * Handles a COPS client-open message
+     * @param    conn Socket to the PEP
+     * @param    msg <tt>COPSMsg</tt> holding the client-open message
+     * @throws COPSException
+     * @throws IOException
+     * TODO - Refactor PCMMPdpAgent#handleClientOpenMsg() as it contains much of this same logic
+     */
+    protected void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
+        final COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
+        _pepId = cMsg.getPepId();
+
+        // Validate Client Type
+        if (msg.getHeader().getClientType() != _clientType) {
+            // Unsupported client type
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
+                    new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+                logger.error("Unexpected exception writing data", unae);
+            }
+
+            throw new COPSException("Unsupported client type");
+        }
+
+        // PEPId is mandatory
+        if (_pepId == null) {
+            // Mandatory COPS object missing
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
+                    new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+                logger.error("Unexpected exception writing data", unae);
+            }
+
+            throw new COPSException("Mandatory COPS object missing (PEPId)");
+        }
+
+        // Support
+        if ( (cMsg.getClientSI() != null) || (cMsg.getPdpAddress() != null) || (cMsg.getIntegrity() != null)) {
+            // Unsupported objects
+            final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
+                    new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
+            try {
+                closeMsg.writeData(conn);
+            } catch (IOException unae) {
+                logger.error("Exception writing data", unae);
+            }
+
+            throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");
+        }
+
+        // Connection accepted
+        final COPSClientAcceptMsg acceptMsg;
+        if (_acctTimer != 0)
+            acceptMsg = new COPSClientAcceptMsg(_clientType, new COPSKATimer(_kaTimer),
+                new COPSAcctTimer(_acctTimer), null);
+        else
+            acceptMsg = new COPSClientAcceptMsg(_clientType, new COPSKATimer(_kaTimer),null, null);
+        acceptMsg.writeData(conn);
+
+        final COPSPdpConnection pdpConn = new COPSPdpConnection(_pepId, conn,  _process);
+        pdpConn.setKaTimer(_kaTimer);
+        if (_acctTimer != 0) pdpConn.setAcctTimer(_acctTimer);
+        new Thread(pdpConn).start();
+        _connectionMap.put(_pepId.getData().str(), pdpConn);
+    }
+
+}
+
+
+