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.OPCode;
8 import java.io.IOException;
9 import java.net.Socket;
10 import java.util.Date;
12 import java.util.concurrent.ConcurrentHashMap;
15 * Class for managing an outsourcing connection at the PDP side.
17 public class COPSPdpOSConnection implements Runnable {
19 public final static Logger logger = LoggerFactory.getLogger(COPSPdpOSConnection.class);
22 Socket connected to PEP
29 private COPSPepId _pepId;
32 Time of the latest keep-alive sent
37 * Time of the latest keep-alive received
39 protected Date _lastRecKa;
42 Maps a Client Handle to a Handler
44 protected final Map<String, COPSPdpOSReqStateMan> _managerMap;
47 * PDP policy data processor class
49 protected COPSPdpOSDataProcess _process;
52 Accounting timer value (secs)
54 protected short _acctTimer;
57 Keep-alive timer value (secs)
59 protected short _kaTimer;
62 COPS error returned by PEP
64 protected COPSError _error;
67 * Creates a new PDP connection
69 * @param pepId PEP-ID of the connected PEP
70 * @param sock Socket connected to PEP
71 * @param process Object for processing policy data
73 public COPSPdpOSConnection(COPSPepId pepId, Socket sock, COPSPdpOSDataProcess process) {
78 _managerMap = new ConcurrentHashMap<>();
85 * Gets the time of that latest keep-alive sent
86 * @return Time of that latest keep-alive sent
88 public Date getLastKAlive() {
93 * Sets the keep-alive timer value
94 * @param kaTimer Keep-alive timer value (secs)
96 public void setKaTimer(short kaTimer) {
101 * Gets the keep-alive timer value
102 * @return Keep-alive timer value (secs)
104 public short getKaTimer() {
109 * Sets the accounting timer value
110 * @param acctTimer Accounting timer value (secs)
112 public void setAccTimer(short acctTimer) {
113 _acctTimer = acctTimer;
117 * Gets the accounting timer value
118 * @return Accounting timer value (secs)
120 public short getAcctTimer() {
126 * @return The ID of the PEP, as a <tt>String</tt>
128 public String getPepId() {
129 return _pepId.getData().str();
133 * Checks whether the socket to the PEP is closed or not
134 * @return <tt>true</tt> if closed, <tt>false</tt> otherwise
136 public boolean isClosed() {
137 return _sock.isClosed();
141 * Closes the socket to the PEP
142 * @throws IOException
144 protected void close()
150 * Gets the socket to the PEP
151 * @return Socket connected to the PEP
153 public Socket getSocket() {
161 Date _lastSendKa = new Date();
162 _lastRecKa = new Date();
164 while (!_sock.isClosed()) {
165 if (_sock.getInputStream().available() != 0) {
166 // _lastmessage = processMessage(_sock);
167 processMessage(_sock);
168 _lastRecKa = new Date();
174 int _startTime = (int) (_lastRecKa.getTime());
175 int cTime = (int) (new Date().getTime());
177 if ((cTime - _startTime) > _kaTimer*1000) {
179 // Notify all Request State Managers
180 notifyNoKAAllReqStateMan();
184 _startTime = (int) (_lastSendKa.getTime());
185 cTime = (int) (new Date().getTime());
187 if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
188 // TODO - is 0 ok for a clientType here???
189 final COPSKAMsg msg = new COPSKAMsg(null);
190 COPSTransceiver.sendMsg(msg, _sock);
191 _lastSendKa = new Date();
197 } catch (Exception e) {
198 logger.error("Exception caught while sleeping", e);
202 } catch (Exception e) {
203 logger.error("Error processing COPS message from socket", e);
206 // connection closed by server
207 // COPSDebug.out(getClass().getName(),"Connection closed by client");
210 } catch (IOException e) {
211 logger.error("Error closing socket", e);
214 // Notify all Request State Managers
216 notifyCloseAllReqStateMan();
217 } catch (COPSPdpException e) {
218 logger.error("Error closing state managers", e);
223 * Gets a COPS message from the socket and processes it
224 * @param conn Socket connected to the PEP
226 private void processMessage(final Socket conn) throws COPSException, IOException {
227 final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
229 if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
230 handleClientCloseMsg(conn, msg);
231 } else if (msg.getHeader().getOpCode().equals(OPCode.KA)) {
232 handleKeepAliveMsg(conn, msg);
233 } else if (msg.getHeader().getOpCode().equals(OPCode.REQ)) {
234 handleRequestMsg(conn, msg);
235 } else if (msg.getHeader().getOpCode().equals(OPCode.RPT)) {
236 handleReportMsg(conn, msg);
237 } else if (msg.getHeader().getOpCode().equals(OPCode.DRQ)) {
238 handleDeleteRequestMsg(conn, msg);
239 } else if (msg.getHeader().getOpCode().equals(OPCode.SSC)) {
240 handleSyncComplete(conn, msg);
242 throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
247 * Handle Client Close Message, close the passed connection
249 * @param conn a Socket
250 * @param msg a COPSMsg
253 * <Client-Close> ::= <Common Header>
257 * Not support [<Integrity>]
260 private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
261 COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
262 _error = cMsg.getError();
264 // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
265 // conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
269 if (cMsg.getIntegrity() != null) {
270 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
274 } catch (Exception unae) {
275 logger.error("Unexpected exception while closing the connection", unae);
280 * Gets the occurred COPS Error
281 * @return <tt>COPSError</tt> object
283 protected COPSError getError() {
288 * Handle Keep Alive Message
290 * <Keep-Alive> ::= <Common Header>
293 * Not support [<Integrity>]
295 * @param conn a Socket
296 * @param msg a COPSMsg
299 private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
300 COPSKAMsg cMsg = (COPSKAMsg) msg;
302 COPSKAMsg kaMsg = (COPSKAMsg) msg;
305 if (cMsg.getIntegrity() != null) {
306 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
309 kaMsg.writeData(conn);
310 } catch (Exception unae) {
311 logger.error("Unexpected exception writing COPS data", unae);
316 * Handle Delete Request Message
318 * <Delete Request> ::= <Common Header>
323 * Not support [<Integrity>]
325 * @param conn a Socket
326 * @param msg a COPSMsg
329 private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)
330 throws COPSPdpException {
331 COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
332 // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +
333 // conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");
336 if (cMsg.getIntegrity() != null) {
337 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
340 // Delete clientHandler
341 if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
342 logger.warn("Missing state manager for for ClientHandle" + cMsg.getClientHandle().getId().str());
345 final COPSPdpOSReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
347 logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());
349 man.processDeleteRequestState(cMsg);
355 * Handle Request Message
357 * <Request> ::= <Common Header>
360 * *(<Named ClientSI>)
362 * <Named ClientSI> ::= <*(<PRID> <EPD>)>
364 * Not support [<Integrity>]
366 * @param conn a Socket
367 * @param msg a COPSMsg
370 private void handleRequestMsg(final Socket conn, final COPSMsg msg) throws COPSException {
371 final COPSReqMsg reqMsg = (COPSReqMsg) msg;
372 final COPSHeader header = reqMsg.getHeader();
373 final short cType = header.getClientType();
376 if (reqMsg.getIntegrity() != null) {
377 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
380 final COPSPdpOSReqStateMan man;
381 if (_managerMap.get(reqMsg.getClientHandle().getId().str()) == null) {
382 man = new COPSPdpOSReqStateMan(cType, reqMsg.getClientHandle(), _process);
383 _managerMap.put(reqMsg.getClientHandle().getId().str(), man);
384 man.initRequestState(_sock);
386 man = _managerMap.get(reqMsg.getClientHandle().getId().str());
388 man.processRequest(reqMsg);
392 * Handle Report Message
394 * <Report State> ::= <Common Header>
397 * *(<Named ClientSI>)
400 * Not support [<Integrity>]
402 * @param conn a Socket
403 * @param msg a COPSMsg
406 private void handleReportMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
407 COPSReportMsg repMsg = (COPSReportMsg) msg;
408 // COPSHandle handle = repMsg.getClientHandle();
409 // COPSHeader header = repMsg.getHeader();
412 if (repMsg.getIntegrity() != null) {
413 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
416 COPSPdpOSReqStateMan man = _managerMap.get(repMsg.getClientHandle().getId().str());
418 logger.warn("State manager not found for ID - " + repMsg.getClientHandle().getId().str());
420 man.processReport(repMsg);
425 * Method handleSyncComplete
427 * @param conn a Socket
428 * @param msg a COPSMsg
431 private void handleSyncComplete(final Socket conn, final COPSMsg msg) throws COPSException {
432 final COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
435 if (cMsg.getIntegrity() != null) {
436 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
439 final COPSPdpOSReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
441 logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());
443 man.processSyncComplete(cMsg);
448 * Requests a COPS sync from the PEP
449 * @throws COPSPdpException
451 protected void syncAllRequestState() throws COPSException {
452 for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
453 man.syncRequestState();
457 private void notifyCloseAllReqStateMan() throws COPSPdpException {
458 for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
459 man.processClosedConnection(_error);
463 private void notifyNoKAAllReqStateMan() throws COPSPdpException {
464 for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
465 man.processNoKAConnection();