7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9 import org.umu.cops.prpdp.COPSPdpException;
10 import org.umu.cops.stack.*;
11 import org.umu.cops.stack.COPSHeader.ClientType;
12 import org.umu.cops.stack.COPSHeader.OPCode;
14 import java.io.IOException;
15 import java.net.Socket;
16 import java.util.Date;
17 import java.util.HashMap;
19 import java.util.concurrent.ConcurrentHashMap;
22 * Class for managing an provisioning connection at the PDP side.
24 public class PCMMPdpConnection implements Runnable {
27 public final static Logger logger = LoggerFactory.getLogger(PCMMPdpConnection.class);
30 Socket connected to PEP
37 private COPSPepId _pepId;
40 * Time of the latest keep-alive received
42 protected Date _lastRecKa;
45 Maps a Client Handle to a Handler
47 protected Map<String, PCMMPdpReqStateMan> _managerMap;
50 * PDP policy data processor class
52 protected PCMMPdpDataProcess _process;
55 Accounting timer value (secs)
57 protected short _acctTimer;
60 Keep-alive timer value (secs)
62 protected short _kaTimer;
65 COPS error returned by PEP
67 protected COPSError _error;
70 * Creates a new PDP connection
72 * @param pepId PEP-ID of the connected PEP
73 * @param sock Socket connected to PEP
74 * @param process Object for processing policy data
76 public PCMMPdpConnection(COPSPepId pepId, Socket sock, PCMMPdpDataProcess process) {
79 _managerMap = new ConcurrentHashMap<>();
85 * Sets the keep-alive timer value
86 * @param kaTimer Keep-alive timer value (secs)
88 public void setKaTimer(final short kaTimer) {
93 * Sets the accounting timer value
94 * @param acctTimer Accounting timer value (secs)
96 public void setAccTimer(final short acctTimer) {
97 _acctTimer = acctTimer;
101 * Gets the accounting timer value
102 * @return Accounting timer value (secs)
104 public short getAcctTimer() {
109 * Gets the handle map
110 * @return A <tt>Hashtable</tt> holding the handle map
112 public Map<String, PCMMPdpReqStateMan> getReqStateMans() {
114 return new HashMap<>(_managerMap);
118 * Checks whether the socket to the PEP is closed or not
119 * @return <tt>true</tt> if closed, <tt>false</tt> otherwise
121 public boolean isClosed() {
122 return _sock.isClosed();
126 * Closes the socket to the PEP
127 * @throws IOException
129 protected void close()
135 * Gets the socket to the PEP
136 * @return Socket connected to the PEP
138 public Socket getSocket() {
146 Date _lastSendKa = new Date();
147 _lastRecKa = new Date();
149 while (!_sock.isClosed()) {
150 if (_sock.getInputStream().available() != 0) {
151 processMessage(_sock);
152 _lastRecKa = new Date();
158 int _startTime = (int) (_lastRecKa.getTime());
159 int cTime = (int) (new Date().getTime());
161 if ((cTime - _startTime) > _kaTimer*1000) {
163 // Notify all Request State Managers
164 notifyNoKAAllReqStateMan();
168 _startTime = (int) (_lastSendKa.getTime());
169 cTime = (int) (new Date().getTime());
171 if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
172 // TODO - determine what is the client type to be used here?
173 final COPSKAMsg msg = new COPSKAMsg(ClientType.NA, null);
174 COPSTransceiver.sendMsg(msg, _sock);
175 _lastSendKa = new Date();
181 } catch (Exception e) {
182 logger.error("Unexpected exception while sleeping", e);
186 } catch (Exception e) {
187 logger.error("Error reading messages from socket", e);
190 // connection closed by server
191 // COPSDebug.out(getClass().getName(),"Connection closed by client");
194 } catch (IOException e) {
195 logger.error("Error closing socket", e);
198 // Notify all Request State Managers
200 notifyCloseAllReqStateMan();
201 } catch (COPSPdpException e) {
202 logger.error("Error closing state managers", e);
207 * Gets a COPS message from the socket and processes it
208 * @param conn Socket connected to the PEP
210 private void processMessage(final Socket conn) throws COPSPdpException, COPSException, IOException {
211 final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
213 if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
214 handleClientCloseMsg(conn, msg);
215 } else if (msg.getHeader().getOpCode().equals(OPCode.KA)) {
216 handleKeepAliveMsg(conn, msg);
217 } else if (msg.getHeader().getOpCode().equals(OPCode.REQ)) {
218 handleRequestMsg(conn, msg);
219 } else if (msg.getHeader().getOpCode().equals(OPCode.RPT)) {
220 handleReportMsg(conn, msg);
221 } else if (msg.getHeader().getOpCode().equals(OPCode.DRQ)) {
222 handleDeleteRequestMsg(conn, msg);
223 } else if (msg.getHeader().getOpCode().equals(OPCode.SSQ)) {
224 handleSyncComplete(conn, msg);
226 throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
231 * Handle Client Close Message, close the passed connection
233 * @param conn a Socket
234 * @param msg a COPSMsg
237 * <Client-Close> ::= <Common Header>
241 * Not support [<Integrity>]
244 private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
245 COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
246 _error = cMsg.getError();
249 if (cMsg.getIntegrity() != null) {
250 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
254 } catch (Exception unae) {
255 logger.error("Unexpected exception closing connection", unae);
260 * Gets the occurred COPS Error
261 * @return <tt>COPSError</tt> object
263 protected COPSError getError() {
268 * Handle Keep Alive Message
270 * <Keep-Alive> ::= <Common Header>
273 * Not support [<Integrity>]
275 * @param conn a Socket
276 * @param msg a COPSMsg
279 private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
280 COPSKAMsg cMsg = (COPSKAMsg) msg;
282 COPSKAMsg kaMsg = (COPSKAMsg) msg;
285 if (cMsg.getIntegrity() != null) {
286 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
289 kaMsg.writeData(conn);
290 } catch (Exception unae) {
291 logger.error("Unexpected exception while writing keep-alive message", unae);
296 * Handle Delete Request Message
298 * <Delete Request> ::= <Common Header>
303 * Not support [<Integrity>]
305 * @param conn a Socket
306 * @param msg a COPSMsg
309 private void handleDeleteRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
310 COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
311 // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +
312 // conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");
315 if (cMsg.getIntegrity() != null) {
316 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
319 // Delete clientHandler
320 if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
321 // TODO - Determine what to do here???
322 // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
323 // cMsg.getClientHandle().getId().getData());
326 final PCMMPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
328 logger.warn("State manager not found");
330 man.processDeleteRequestState(cMsg);
336 * Handle Request Message
338 * <Request> ::= <Common Header>
341 * *(<Named ClientSI>)
343 * <Named ClientSI> ::= <*(<PRID> <EPD>)>
345 * Not support [<Integrity>]
347 * @param conn a Socket
348 * @param msg a COPSMsg
351 private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
353 final COPSReqMsg reqMsg = (COPSReqMsg) msg;
354 // COPSContext cntxt = reqMsg.getContext();
355 final COPSHeader header = reqMsg.getHeader();
356 //short reqType = cntxt.getRequestType();
357 final ClientType cType = header.getClientType();
360 if (reqMsg.getIntegrity() != null) {
361 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
364 PCMMPdpReqStateMan man;
365 man = _managerMap.get(reqMsg.getClientHandle().getId().str());
368 man = new PCMMPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());
369 _managerMap.put(reqMsg.getClientHandle().getId().str(), man);
370 man.setDataProcess(_process);
371 man.initRequestState(_sock);
373 // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +
374 // header.getClientType() + " msgType=" +
375 // cntxt.getMessageType() + ", connId=" + conn.toString());
378 man.processRequest(reqMsg);
382 * Handle Report Message
384 * <Report State> ::= <Common Header>
387 * *(<Named ClientSI>)
390 * Not support [<Integrity>]
392 * @param conn a Socket
393 * @param msg a COPSMsg
396 private void handleReportMsg(Socket conn, COPSMsg msg)
397 throws COPSPdpException {
398 COPSReportMsg repMsg = (COPSReportMsg) msg;
399 // COPSHandle handle = repMsg.getClientHandle();
400 // COPSHeader header = repMsg.getHeader();
403 if (repMsg.getIntegrity() != null) {
404 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
407 final PCMMPdpReqStateMan man = _managerMap.get(repMsg.getClientHandle().getId().str());
409 logger.warn("State manager not found");
411 man.processReport(repMsg);
416 * Method handleSyncComplete
418 * @param conn a Socket
419 * @param msg a COPSMsg
422 private void handleSyncComplete(Socket conn, COPSMsg msg)
423 throws COPSPdpException {
424 COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
425 // COPSHandle handle = cMsg.getClientHandle();
426 // COPSHeader header = cMsg.getHeader();
429 if (cMsg.getIntegrity() != null) {
430 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
433 final PCMMPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
435 logger.warn("State manager not found");
437 man.processSyncComplete(cMsg);
442 * Requests a COPS sync from the PEP
443 * @throws COPSException
444 * @throws COPSPdpException
446 protected void syncAllRequestState() throws COPSException, COPSPdpException {
447 for (final PCMMPdpReqStateMan man : _managerMap.values()) {
448 man.syncRequestState();
452 private void notifyCloseAllReqStateMan() throws COPSPdpException {
453 for (final PCMMPdpReqStateMan man : _managerMap.values()) {
454 man.processClosedConnection(_error);
458 private void notifyNoKAAllReqStateMan() throws COPSPdpException {
459 for (final PCMMPdpReqStateMan man : _managerMap.values()) {
460 man.processNoKAConnection();