2 * Copyright (c) 2004 University of Murcia. All rights reserved.
3 * --------------------------------------------------------------
4 * For more information, please see <http://www.umu.euro6ix.org/>.
7 package org.umu.cops.prpdp;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11 import org.umu.cops.stack.*;
12 import org.umu.cops.stack.COPSHeader.ClientType;
14 import java.io.IOException;
15 import java.net.Socket;
16 import java.util.Date;
18 import java.util.concurrent.ConcurrentHashMap;
21 * Class for managing an provisioning connection at the PDP side.
23 public class COPSPdpConnection implements Runnable {
25 public final static Logger logger = LoggerFactory.getLogger(COPSPdpConnection.class);
28 Socket connected to PEP
35 private COPSPepId _pepId;
38 Time of the latest keep-alive sent
43 * Time of the latest keep-alive received
45 protected Date _lastRecKa;
48 Maps a Client Handle to a Handler
50 protected final Map<String, COPSPdpReqStateMan> _managerMap;
53 * PDP policy data processor class
55 protected COPSPdpDataProcess _process;
58 Accounting timer value (secs)
60 protected short _acctTimer;
63 Keep-alive timer value (secs)
65 protected short _kaTimer;
68 COPS error returned by PEP
70 protected COPSError _error;
73 * Creates a new PDP connection
75 * @param pepId PEP-ID of the connected PEP
76 * @param sock Socket connected to PEP
77 * @param process Object for processing policy data
79 public COPSPdpConnection(COPSPepId pepId, Socket sock, COPSPdpDataProcess process) {
84 _managerMap = new ConcurrentHashMap<>();
91 * Gets the time of that latest keep-alive sent
92 * @return Time of that latest keep-alive sent
94 public Date getLastKAlive() {
99 * Sets the keep-alive timer value
100 * @param kaTimer Keep-alive timer value (secs)
102 public void setKaTimer(short kaTimer) {
107 * Gets the keep-alive timer value
108 * @return Keep-alive timer value (secs)
110 public short getKaTimer() {
115 * Sets the accounting timer value
116 * @param acctTimer Accounting timer value (secs)
118 public void setAccTimer(short acctTimer) {
119 _acctTimer = acctTimer;
123 * Gets the accounting timer value
124 * @return Accounting timer value (secs)
126 public short getAcctTimer() {
132 * @return The ID of the PEP, as a <tt>String</tt>
134 public String getPepId() {
135 return _pepId.getData().str();
139 * Checks whether the socket to the PEP is closed or not
140 * @return <tt>true</tt> if closed, <tt>false</tt> otherwise
142 public boolean isClosed() {
143 return _sock.isClosed();
147 * Closes the socket to the PEP
148 * @throws IOException
150 protected void close()
156 * Gets the socket to the PEP
157 * @return Socket connected to the PEP
159 public Socket getSocket() {
167 Date _lastSendKa = new Date();
168 _lastRecKa = new Date();
170 while (!_sock.isClosed()) {
171 if (_sock.getInputStream().available() != 0) {
172 processMessage(_sock);
173 _lastRecKa = new Date();
179 int _startTime = (int) (_lastRecKa.getTime());
180 int cTime = (int) (new Date().getTime());
182 if ((cTime - _startTime) > _kaTimer*1000) {
184 // Notify all Request State Managers
185 notifyNoKAAllReqStateMan();
189 _startTime = (int) (_lastSendKa.getTime());
190 cTime = (int) (new Date().getTime());
192 if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
193 // TODO - what should the real clientType be here???
194 final COPSKAMsg msg = new COPSKAMsg(ClientType.NA, null);
195 COPSTransceiver.sendMsg(msg, _sock);
196 _lastSendKa = new Date();
202 } catch (Exception e) {
203 logger.error("Exception thrown while sleeping", e);
207 } catch (Exception e) {
208 logger.error("Error while processing socket messages", e);
211 // connection closed by server
214 } catch (IOException e) {
215 logger.error("Error closing socket", e);
218 // Notify all Request State Managers
220 notifyCloseAllReqStateMan();
221 } catch (COPSPdpException e) {
222 logger.error("Error closing state managers");
227 * Gets a COPS message from the socket and processes it
228 * @param conn Socket connected to the PEP
230 private void processMessage(final Socket conn) throws COPSPdpException, COPSException, IOException {
231 final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
232 switch (msg.getHeader().getOpCode()) {
234 handleClientCloseMsg(conn, msg);
237 handleKeepAliveMsg(conn, msg);
240 handleRequestMsg(conn, msg);
243 handleReportMsg(conn, msg);
246 handleDeleteRequestMsg(conn, msg);
249 handleSyncComplete(conn, msg);
252 throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
257 * Handle Client Close Message, close the passed connection
259 * @param conn a Socket
260 * @param msg a COPSMsg
263 * <Client-Close> ::= <Common Header>
267 * Not support [<Integrity>]
270 private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
271 COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
272 _error = cMsg.getError();
275 if (cMsg.getIntegrity() != null) {
276 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
279 } catch (Exception unae) {
280 logger.error("Unexpected exception closing connection", unae);
285 * Gets the occurred COPS Error
286 * @return <tt>COPSError</tt> object
288 protected COPSError getError() {
293 * Handle Keep Alive Message
295 * <Keep-Alive> ::= <Common Header>
298 * Not support [<Integrity>]
300 * @param conn a Socket
301 * @param msg a COPSMsg
304 private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
305 COPSKAMsg cMsg = (COPSKAMsg) msg;
307 COPSKAMsg kaMsg = (COPSKAMsg) msg;
310 if (cMsg.getIntegrity() != null) {
311 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
313 kaMsg.writeData(conn);
314 } catch (Exception unae) {
315 logger.error("Unexpected exception while writing COPS data", unae);
320 * Handle Delete Request Message
322 * <Delete Request> ::= <Common Header>
327 * Not support [<Integrity>]
329 * @param conn a Socket
330 * @param msg a COPSMsg
333 private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)
334 throws COPSPdpException {
335 COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
338 if (cMsg.getIntegrity() != null) {
339 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
342 // Delete clientHandler
343 if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
344 // TODO - Do something here
347 COPSPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
349 logger.warn("No state manager found with 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 {
374 final COPSReqMsg reqMsg = (COPSReqMsg) msg;
375 // final COPSContext cntxt = reqMsg.getContext();
376 final COPSHeader header = reqMsg.getHeader();
377 //short reqType = cntxt.getRequestType();
378 final ClientType cType = header.getClientType();
381 if (reqMsg.getIntegrity() != null) {
382 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
385 COPSPdpReqStateMan man = _managerMap.get(reqMsg.getClientHandle().getId().str());
388 man = new COPSPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());
389 _managerMap.put(reqMsg.getClientHandle().getId().str(),man);
390 man.setDataProcess(_process);
391 man.initRequestState(_sock);
393 // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +
394 // header.getClientType() + " msgType=" +
395 // cntxt.getMessageType() + ", connId=" + conn.toString());
398 man.processRequest(reqMsg);
402 * Handle Report Message
404 * <Report State> ::= <Common Header>
407 * *(<Named ClientSI>)
410 * Not support [<Integrity>]
412 * @param conn a Socket
413 * @param msg a COPSMsg
416 private void handleReportMsg(Socket conn, COPSMsg msg)
417 throws COPSPdpException {
418 COPSReportMsg repMsg = (COPSReportMsg) msg;
419 // COPSHandle handle = repMsg.getClientHandle();
420 // COPSHeader header = repMsg.getHeader();
423 if (repMsg.getIntegrity() != null) {
424 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
427 final COPSPdpReqStateMan man = _managerMap.get(repMsg.getClientHandle().getId().str());
429 logger.warn("No state manager found with ID - " + repMsg.getClientHandle().getId().str());
431 man.processReport(repMsg);
436 * Method handleSyncComplete
438 * @param conn a Socket
439 * @param msg a COPSMsg
442 private void handleSyncComplete(Socket conn, COPSMsg msg)
443 throws COPSPdpException {
444 COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
445 // COPSHandle handle = cMsg.getClientHandle();
446 // COPSHeader header = cMsg.getHeader();
449 if (cMsg.getIntegrity() != null) {
450 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
453 COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
455 logger.warn("No state manager found with ID - " + cMsg.getClientHandle().getId().str());
457 man.processSyncComplete(cMsg);
462 * Requests a COPS sync from the PEP
463 * @throws COPSException
464 * @throws COPSPdpException
466 protected void syncAllRequestState() throws COPSException, COPSPdpException {
467 for (final COPSPdpReqStateMan man : _managerMap.values()) {
468 man.syncRequestState();
472 private void notifyCloseAllReqStateMan() throws COPSPdpException {
473 for (final COPSPdpReqStateMan man : _managerMap.values()) {
474 man.processClosedConnection(_error);
478 private void notifyNoKAAllReqStateMan() throws COPSPdpException {
479 for (final COPSPdpReqStateMan man : _managerMap.values()) {
480 man.processNoKAConnection();