1 package org.umu.cops.ospdp;
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.umu.cops.stack.*;
6 import org.umu.cops.stack.COPSHeader.ClientType;
7 import org.umu.cops.stack.COPSHeader.OPCode;
9 import java.io.IOException;
10 import java.net.Socket;
11 import java.util.Date;
13 import java.util.concurrent.ConcurrentHashMap;
16 * Class for managing an outsourcing connection at the PDP side.
18 public class COPSPdpOSConnection implements Runnable {
20 public final static Logger logger = LoggerFactory.getLogger(COPSPdpOSConnection.class);
23 Socket connected to PEP
30 private COPSPepId _pepId;
33 Time of the latest keep-alive sent
38 * Time of the latest keep-alive received
40 protected Date _lastRecKa;
43 Maps a Client Handle to a Handler
45 protected final Map<String, COPSPdpOSReqStateMan> _managerMap;
48 * PDP policy data processor class
50 protected COPSPdpOSDataProcess _process;
53 Accounting timer value (secs)
55 protected short _acctTimer;
58 Keep-alive timer value (secs)
60 protected short _kaTimer;
63 COPS error returned by PEP
65 protected COPSError _error;
68 * Creates a new PDP connection
70 * @param pepId PEP-ID of the connected PEP
71 * @param sock Socket connected to PEP
72 * @param process Object for processing policy data
74 public COPSPdpOSConnection(COPSPepId pepId, Socket sock, COPSPdpOSDataProcess process) {
79 _managerMap = new ConcurrentHashMap<>();
86 * Gets the time of that latest keep-alive sent
87 * @return Time of that latest keep-alive sent
89 public Date getLastKAlive() {
94 * Sets the keep-alive timer value
95 * @param kaTimer Keep-alive timer value (secs)
97 public void setKaTimer(short kaTimer) {
102 * Gets the keep-alive timer value
103 * @return Keep-alive timer value (secs)
105 public short getKaTimer() {
110 * Sets the accounting timer value
111 * @param acctTimer Accounting timer value (secs)
113 public void setAccTimer(short acctTimer) {
114 _acctTimer = acctTimer;
118 * Gets the accounting timer value
119 * @return Accounting timer value (secs)
121 public short getAcctTimer() {
127 * @return The ID of the PEP, as a <tt>String</tt>
129 public String getPepId() {
130 return _pepId.getData().str();
134 * Checks whether the socket to the PEP is closed or not
135 * @return <tt>true</tt> if closed, <tt>false</tt> otherwise
137 public boolean isClosed() {
138 return _sock.isClosed();
142 * Closes the socket to the PEP
143 * @throws IOException
145 protected void close()
151 * Gets the socket to the PEP
152 * @return Socket connected to the PEP
154 public Socket getSocket() {
162 Date _lastSendKa = new Date();
163 _lastRecKa = new Date();
165 while (!_sock.isClosed()) {
166 if (_sock.getInputStream().available() != 0) {
167 // _lastmessage = processMessage(_sock);
168 processMessage(_sock);
169 _lastRecKa = new Date();
175 int _startTime = (int) (_lastRecKa.getTime());
176 int cTime = (int) (new Date().getTime());
178 if ((cTime - _startTime) > _kaTimer*1000) {
180 // Notify all Request State Managers
181 notifyNoKAAllReqStateMan();
185 _startTime = (int) (_lastSendKa.getTime());
186 cTime = (int) (new Date().getTime());
188 if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
189 // TODO - is 0 ok for a clientType here???
190 final COPSKAMsg msg = new COPSKAMsg(ClientType.NA, null);
191 COPSTransceiver.sendMsg(msg, _sock);
192 _lastSendKa = new Date();
198 } catch (Exception e) {
199 logger.error("Exception caught while sleeping", e);
203 } catch (Exception e) {
204 logger.error("Error processing COPS message from socket", e);
207 // connection closed by server
208 // COPSDebug.out(getClass().getName(),"Connection closed by client");
211 } catch (IOException e) {
212 logger.error("Error closing socket", e);
215 // Notify all Request State Managers
217 notifyCloseAllReqStateMan();
218 } catch (COPSPdpException e) {
219 logger.error("Error closing state managers", e);
224 * Gets a COPS message from the socket and processes it
225 * @param conn Socket connected to the PEP
227 private void processMessage(Socket conn) throws COPSPdpException, COPSException, IOException {
228 COPSMsg msg = COPSTransceiver.receiveMsg(conn);
230 if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
231 handleClientCloseMsg(conn, msg);
232 } else if (msg.getHeader().getOpCode().equals(OPCode.KA)) {
233 handleKeepAliveMsg(conn, msg);
234 } else if (msg.getHeader().getOpCode().equals(OPCode.REQ)) {
235 handleRequestMsg(conn, msg);
236 } else if (msg.getHeader().getOpCode().equals(OPCode.RPT)) {
237 handleReportMsg(conn, msg);
238 } else if (msg.getHeader().getOpCode().equals(OPCode.DRQ)) {
239 handleDeleteRequestMsg(conn, msg);
240 } else if (msg.getHeader().getOpCode().equals(OPCode.SSC)) {
241 handleSyncComplete(conn, msg);
243 throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
248 * Handle Client Close Message, close the passed connection
250 * @param conn a Socket
251 * @param msg a COPSMsg
254 * <Client-Close> ::= <Common Header>
258 * Not support [<Integrity>]
261 private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
262 COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
263 _error = cMsg.getError();
265 // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
266 // conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
270 if (cMsg.getIntegrity() != null) {
271 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
275 } catch (Exception unae) {
276 logger.error("Unexpected exception while closing the connection", unae);
281 * Gets the occurred COPS Error
282 * @return <tt>COPSError</tt> object
284 protected COPSError getError() {
289 * Handle Keep Alive Message
291 * <Keep-Alive> ::= <Common Header>
294 * Not support [<Integrity>]
296 * @param conn a Socket
297 * @param msg a COPSMsg
300 private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
301 COPSKAMsg cMsg = (COPSKAMsg) msg;
303 COPSKAMsg kaMsg = (COPSKAMsg) msg;
306 if (cMsg.getIntegrity() != null) {
307 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
310 kaMsg.writeData(conn);
311 } catch (Exception unae) {
312 logger.error("Unexpected exception writing COPS data", unae);
317 * Handle Delete Request Message
319 * <Delete Request> ::= <Common Header>
324 * Not support [<Integrity>]
326 * @param conn a Socket
327 * @param msg a COPSMsg
330 private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)
331 throws COPSPdpException {
332 COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
333 // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +
334 // conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");
337 if (cMsg.getIntegrity() != null) {
338 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
341 // Delete clientHandler
342 if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
343 // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
344 // cMsg.getClientHandle().getId().getData());
347 final COPSPdpOSReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
349 logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());
351 man.processDeleteRequestState(cMsg);
357 * Handle Request Message
359 * <Request> ::= <Common Header>
362 * *(<Named ClientSI>)
364 * <Named ClientSI> ::= <*(<PRID> <EPD>)>
366 * Not support [<Integrity>]
368 * @param conn a Socket
369 * @param msg a COPSMsg
372 private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
373 final COPSReqMsg reqMsg = (COPSReqMsg) msg;
374 final COPSHeader header = reqMsg.getHeader();
375 final ClientType cType = header.getClientType();
378 if (reqMsg.getIntegrity() != null) {
379 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
382 final COPSPdpOSReqStateMan man;
383 if (_managerMap.get(reqMsg.getClientHandle().getId().str()) == null) {
384 man = new COPSPdpOSReqStateMan(cType, reqMsg.getClientHandle().getId().str());
385 _managerMap.put(reqMsg.getClientHandle().getId().str(),man);
386 man.setDataProcess(_process);
387 man.initRequestState(_sock);
389 man = _managerMap.get(reqMsg.getClientHandle().getId().str());
391 man.processRequest(reqMsg);
395 * Handle Report Message
397 * <Report State> ::= <Common Header>
400 * *(<Named ClientSI>)
403 * Not support [<Integrity>]
405 * @param conn a Socket
406 * @param msg a COPSMsg
409 private void handleReportMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
410 COPSReportMsg repMsg = (COPSReportMsg) msg;
411 // COPSHandle handle = repMsg.getClientHandle();
412 // COPSHeader header = repMsg.getHeader();
415 if (repMsg.getIntegrity() != null) {
416 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
419 COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());
421 logger.warn("State manager not found for ID - " + repMsg.getClientHandle().getId().str());
423 man.processReport(repMsg);
428 * Method handleSyncComplete
430 * @param conn a Socket
431 * @param msg a COPSMsg
434 private void handleSyncComplete(Socket conn, COPSMsg msg)
435 throws COPSPdpException {
436 COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
437 // COPSHandle handle = cMsg.getClientHandle();
438 // COPSHeader header = cMsg.getHeader();
441 if (cMsg.getIntegrity() != null) {
442 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
445 COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
447 logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());
449 man.processSyncComplete(cMsg);
454 * Requests a COPS sync from the PEP
455 * @throws COPSException
456 * @throws COPSPdpException
458 protected void syncAllRequestState() throws COPSException, COPSPdpException {
459 for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
460 man.syncRequestState();
464 private void notifyCloseAllReqStateMan() throws COPSPdpException {
465 for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
466 man.processClosedConnection(_error);
470 private void notifyNoKAAllReqStateMan() throws COPSPdpException {
471 for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
472 man.processNoKAConnection();