--- /dev/null
+package org.umu.cops.ospep;\r
+\r
+import java.io.IOException;\r
+import java.net.Socket;\r
+import java.util.Date;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+import org.umu.cops.common.COPSDebug;\r
+import org.umu.cops.stack.COPSClientCloseMsg;\r
+import org.umu.cops.stack.COPSDecisionMsg;\r
+import org.umu.cops.stack.COPSError;\r
+import org.umu.cops.stack.COPSException;\r
+import org.umu.cops.stack.COPSHandle;\r
+import org.umu.cops.stack.COPSHeader;\r
+import org.umu.cops.stack.COPSKAMsg;\r
+import org.umu.cops.stack.COPSMsg;\r
+import org.umu.cops.stack.COPSSyncStateMsg;\r
+import org.umu.cops.stack.COPSTransceiver;\r
+\r
+/**\r
+ * COPSPepConnection represents a PEP-PDP Connection Manager.\r
+ * Responsible for processing messages received from PDP.\r
+ */\r
+public class COPSPepOSConnection implements Runnable {\r
+ /** Socket connected to PDP */\r
+ protected Socket _sock;\r
+\r
+ /** Time to wait responses (milliseconds), default is 10 seconds */\r
+ protected int _responseTime;\r
+\r
+ /** COPS Client-type */\r
+ protected short _clientType;\r
+\r
+ /**\r
+ Accounting timer value (secs)\r
+ */\r
+ protected short _acctTimer;\r
+\r
+ /**\r
+ Keep-alive timer value (secs)\r
+ */\r
+ protected short _kaTimer;\r
+\r
+ /**\r
+ * Time of the latest keep-alive received\r
+ */\r
+ protected Date _lastRecKa;\r
+\r
+ /**\r
+ Opcode of the latest message sent\r
+ */\r
+ protected byte _lastmessage;\r
+\r
+ /**\r
+ Maps a COPS Client Handle to a Request State Manager\r
+ */\r
+ protected Hashtable _managerMap;\r
+ // map < String(COPSHandle), COPSPepOSReqStateMan>;\r
+\r
+ /**\r
+ COPS error returned by PDP\r
+ */\r
+ protected COPSError _error;\r
+\r
+ /**\r
+ * Creates a new PEP connection\r
+ * @param clientType PEP's client-type\r
+ * @param sock Socket connected to PDP\r
+ */\r
+ public COPSPepOSConnection(short clientType, Socket sock) {\r
+ _clientType = clientType;\r
+ _sock = sock;\r
+\r
+ // Timers\r
+ _acctTimer = 0;\r
+ _kaTimer = 0;\r
+ _responseTime = 10000;\r
+ _lastmessage = COPSHeader.COPS_OP_CAT;\r
+\r
+ _managerMap = new Hashtable(20);\r
+ }\r
+\r
+ /**\r
+ * Gets the response time\r
+ * @return Response time value (msecs)\r
+ */\r
+ public int getResponseTime() {\r
+ return _responseTime;\r
+ }\r
+\r
+ /**\r
+ * Gets the socket connected to the PDP\r
+ * @return Socket connected to PDP\r
+ */\r
+ public Socket getSocket() {\r
+ return _sock;\r
+ }\r
+\r
+ /**\r
+ * Gets keep-alive timer\r
+ * @return Keep-alive timer value (secs)\r
+ */\r
+ public short getKaTimer () {\r
+ return _kaTimer;\r
+ }\r
+\r
+ /**\r
+ * Gets accounting timer\r
+ * @return Accounting timer value (secs)\r
+ */\r
+ public short getAcctTimer () {\r
+ return _acctTimer;\r
+ }\r
+\r
+ /**\r
+ * Gets active COPS handles\r
+ * @return An <tt>Enumeration</tt> holding all active handles\r
+ */\r
+ protected Enumeration getHandles() {\r
+ return _managerMap.keys();\r
+ }\r
+\r
+ /**\r
+ * Gets all request state managers\r
+ * @return A <tt>Hashatable</tt> holding all request state managers\r
+ */\r
+ protected Hashtable getReqStateMans() {\r
+ return _managerMap;\r
+ }\r
+\r
+ /**\r
+ * Checks whether the socket to the PDP is closed or not\r
+ * @return <tt>true</tt> if the socket is closed, <tt>false</tt> otherwise\r
+ */\r
+ public boolean isClosed() {\r
+ return _sock.isClosed();\r
+ }\r
+\r
+ /**\r
+ * Closes the socket\r
+ *\r
+ * @throws java.io.IOException\r
+ */\r
+ protected void close() throws IOException {\r
+ _sock.close();\r
+ }\r
+\r
+ /**\r
+ * Gets the opcode of the lastest message sent\r
+ * @return Message opcode\r
+ */\r
+ public byte getLastmessage() {\r
+ return _lastmessage;\r
+ }\r
+\r
+ /**\r
+ * Sets response time\r
+ * @param respTime Response time value (msecs)\r
+ */\r
+ public void setResponseTime(int respTime) {\r
+ _responseTime = respTime;\r
+ };\r
+\r
+ /**\r
+ * Sets keep-alive timer\r
+ * @param kaTimer Keep-alive timer value (secs)\r
+ */\r
+ public void setKaTimer(short kaTimer) {\r
+ _kaTimer = kaTimer;\r
+ }\r
+\r
+ /**\r
+ * Sets accounting timer\r
+ * @param acctTimer Accounting timer value (secs)\r
+ */\r
+ public void setAcctTimer(short acctTimer) {\r
+ _acctTimer = acctTimer;\r
+ }\r
+\r
+ /**\r
+ * Message-processing loop\r
+ */\r
+ public void run () {\r
+ Date _lastSendKa = new Date();\r
+ Date _lastSendAcc = new Date();\r
+ _lastRecKa = new Date();\r
+\r
+ try {\r
+ while (!_sock.isClosed()) {\r
+ if (_sock.getInputStream().available() != 0) {\r
+ _lastmessage = processMessage(_sock);\r
+ _lastRecKa = new Date();\r
+ }\r
+\r
+ // Keep Alive\r
+ if (_kaTimer > 0) {\r
+ // Timeout del PDP\r
+ int _startTime = (int) (_lastRecKa.getTime());\r
+ int cTime = (int) (new Date().getTime());\r
+\r
+ if ((int)(cTime - _startTime) > _kaTimer*1000) {\r
+ _sock.close();\r
+ // Notify all Request State Managers\r
+ notifyNoKAAllReqStateMan();\r
+ }\r
+\r
+ // Send to PEP\r
+ _startTime = (int) (_lastSendKa.getTime());\r
+ cTime = (int) (new Date().getTime());\r
+\r
+ if ((int)(cTime - _startTime) > ((_kaTimer*3/4) * 1000)) {\r
+ COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);\r
+ COPSKAMsg msg = new COPSKAMsg();\r
+\r
+ msg.add(hdr);\r
+\r
+ COPSTransceiver.sendMsg(msg, _sock);\r
+ _lastSendKa = new Date();\r
+ }\r
+ }\r
+\r
+ // Accounting\r
+ if (_acctTimer > 0) {\r
+ int _startTime = (int) (_lastSendAcc.getTime());\r
+ int cTime = (int) (new Date().getTime());\r
+\r
+ if ((int)(cTime - _startTime) > ((_acctTimer*3/4)*1000)) {\r
+ // Notify all Request State Managers\r
+ notifyAcctAllReqStateMan();\r
+ _lastSendAcc = new Date();\r
+ }\r
+ }\r
+\r
+ try {\r
+ Thread.sleep(500);\r
+ } catch (Exception e) {};\r
+ }\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ COPSDebug.err(getClass().getName(), COPSDebug.ERROR_SOCKET, e);\r
+ }\r
+\r
+ // connection closed by server\r
+ // COPSDebug.out(getClass().getName(),"Connection closed by server");\r
+ try {\r
+ _sock.close();\r
+ } catch (IOException e) {};\r
+\r
+ // Notify all Request State Managers\r
+ try {\r
+ notifyCloseAllReqStateMan();\r
+ } catch (COPSPepException e) {};\r
+ }\r
+\r
+ /**\r
+ * Gets a COPS message from the socket and processes it\r
+ * @param conn Socket connected to the PDP\r
+ * @return COPS message type\r
+ * @throws COPSPepException\r
+ * @throws COPSException\r
+ * @throws IOException\r
+ */\r
+ protected byte processMessage(Socket conn) throws COPSPepException, COPSException, IOException {\r
+ COPSMsg msg = COPSTransceiver.receiveMsg(conn);\r
+\r
+ if (msg.getHeader().isAClientClose()) {\r
+ handleClientCloseMsg(conn, msg);\r
+ return COPSHeader.COPS_OP_CC;\r
+ } else if (msg.getHeader().isADecision()) {\r
+ handleDecisionMsg(/*OJO conn, */msg);\r
+ return COPSHeader.COPS_OP_DEC;\r
+ } else if (msg.getHeader().isASyncStateReq()) {\r
+ handleSyncStateReqMsg(conn, msg);\r
+ return COPSHeader.COPS_OP_SSQ;\r
+ } else if (msg.getHeader().isAKeepAlive()) {\r
+ handleKeepAliveMsg(conn, msg);\r
+ return COPSHeader.COPS_OP_KA;\r
+ } else {\r
+ throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Handle Client Close Message, close the passed connection\r
+ *\r
+ * @param conn a Socket\r
+ * @param msg a COPSMsg\r
+ *\r
+ *\r
+ * <Client-Close> ::= <Common Header>\r
+ * <Error>\r
+ * [<Integrity>]\r
+ *\r
+ * Not support [<Integrity>]\r
+ *\r
+ */\r
+ private void handleClientCloseMsg(Socket conn, COPSMsg msg) {\r
+ COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;\r
+ _error = cMsg.getError();\r
+\r
+ // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +\r
+ // conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");\r
+\r
+ try {\r
+ // Support\r
+ if (cMsg.getIntegrity() != null)\r
+ COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED, "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+\r
+ conn.close();\r
+ } catch (Exception unae) { };\r
+ }\r
+\r
+ /**\r
+ * Gets the COPS error\r
+ * @return <tt>COPSError</tt> returned by PDP\r
+ */\r
+ protected COPSError getError() {\r
+ return _error;\r
+ }\r
+\r
+ /**\r
+ * Handle Keep Alive Message\r
+ *\r
+ * <Keep-Alive> ::= <Common Header>\r
+ * [<Integrity>]\r
+ *\r
+ * Not support [<Integrity>]\r
+ *\r
+ * @param conn a Socket\r
+ * @param msg a COPSMsg\r
+ *\r
+ */\r
+ private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {\r
+ COPSKAMsg cMsg = (COPSKAMsg) msg;\r
+\r
+ // COPSDebug.out(getClass().getName(),"Get KAlive Msg");\r
+\r
+ try {\r
+ // Support\r
+ if (cMsg.getIntegrity() != null)\r
+ COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED, "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+\r
+ // must we do anything else?\r
+\r
+ } catch (Exception unae) { };\r
+ }\r
+\r
+ /**\r
+ * Method handleDecisionMsg\r
+ *\r
+ * <Decision Message> ::= <Common Header: Flag SOLICITED>\r
+ * <Client Handle>\r
+ * *(<Decision>) | <Error>\r
+ * [<Integrity>]\r
+ * <Decision> ::= <Context>\r
+ * <Decision: Flags>\r
+ * [<ClientSI Decision Data: Outsourcing>]\r
+ * <Decision: Flags> ::= <Command-Code> NULLFlag\r
+ * <Command-Code> ::= NULLDecision | Install | Remove\r
+ * <ClientSI Decision Data> ::= <<Install Decision> | <Remove Decision>>\r
+ * <Install Decision> ::= *(<PRID> <EPD>)\r
+ * <Remove Decision> ::= *(<PRID> | <PPRID>)\r
+ *\r
+ * @param msg a COPSMsg\r
+ *\r
+ */\r
+ private void handleDecisionMsg(/*OJO Socket conn, */COPSMsg msg) throws COPSPepException {\r
+ COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;\r
+ COPSHandle handle = dMsg.getClientHandle();\r
+ COPSPepOSReqStateMan manager = (COPSPepOSReqStateMan) _managerMap.get(handle.getId().str());\r
+ manager.processDecision(dMsg);\r
+ }\r
+\r
+ /**\r
+ * Method handleSyncStateReqMsg\r
+ *\r
+ * <Synchronize State> ::= <Common Header>\r
+ * [<Client Handle>]\r
+ * [<Integrity>]\r
+ *\r
+ * @param conn a Socket\r
+ * @param msg a COPSMsg\r
+ *\r
+ */\r
+ private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {\r
+ COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;\r
+ // COPSHandle handle = cMsg.getClientHandle();\r
+ // COPSHeader header = cMsg.getHeader();\r
+\r
+ // Support\r
+ if (cMsg.getIntegrity() != null)\r
+ COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOSUPPORTED,\r
+ "Unsupported objects (Integrity) to connection " + conn.getInetAddress());\r
+\r
+ COPSPepOSReqStateMan manager = (COPSPepOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());\r
+\r
+ if (manager == null)\r
+ COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);\r
+ else\r
+ manager.processSyncStateRequest(cMsg);\r
+ }\r
+\r
+ /**\r
+ * Adds a new request state\r
+ * @param clientHandle Client's handle\r
+ * @param process Policy data processing object\r
+ * @param clientSIs Client data from the outsourcing event\r
+ * @return The newly created request state manager\r
+ * @throws COPSException\r
+ * @throws COPSPepException\r
+ */\r
+ protected COPSPepOSReqStateMan addRequestState(String clientHandle, COPSPepOSDataProcess process, Vector clientSIs) throws COPSException, COPSPepException {\r
+ COPSPepOSReqStateMan manager = new COPSPepOSReqStateMan(_clientType, clientHandle);\r
+ if (_managerMap.get(clientHandle) != null)\r
+ throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);\r
+\r
+ manager.setDataProcess(process);\r
+ manager.setClientSI(clientSIs);\r
+ _managerMap.put(clientHandle, manager);\r
+ manager.initRequestState(_sock);\r
+ return manager;\r
+ }\r
+\r
+ /**\r
+ * Deletes a request state\r
+ * @param manager Request state manager\r
+ * @throws COPSException\r
+ * @throws COPSPepException\r
+ */\r
+ protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException, COPSPepException {\r
+ manager.finalizeRequestState();\r
+ }\r
+\r
+ private void notifyCloseAllReqStateMan() throws COPSPepException {\r
+ if (_managerMap.size() > 0) {\r
+ for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+ String handle = (String) e.nextElement();\r
+ COPSPepOSReqStateMan man = (COPSPepOSReqStateMan) _managerMap.get(handle);\r
+\r
+ man.processClosedConnection(_error);\r
+ }\r
+ }\r
+ }\r
+\r
+ private void notifyNoKAAllReqStateMan() throws COPSPepException {\r
+ if (_managerMap.size() > 0) {\r
+ for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+ String handle = (String) e.nextElement();\r
+ COPSPepOSReqStateMan man = (COPSPepOSReqStateMan) _managerMap.get(handle);\r
+\r
+ man.processNoKAConnection();\r
+ }\r
+ }\r
+ }\r
+\r
+ private void notifyAcctAllReqStateMan() throws COPSPepException {\r
+ if (_managerMap.size() > 0) {\r
+ for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {\r
+ String handle = (String) e.nextElement();\r
+ COPSPepOSReqStateMan man = (COPSPepOSReqStateMan) _managerMap.get(handle);\r
+\r
+ man.processAcctReport();\r
+ }\r
+ }\r
+ }\r
+\r
+}\r