2 * Copyright (c) 2004 University of Murcia. All rights reserved.
\r
3 * --------------------------------------------------------------
\r
4 * For more information, please see <http://www.umu.euro6ix.org/>.
\r
7 package org.umu.cops.prpdp;
\r
9 import org.slf4j.Logger;
\r
10 import org.slf4j.LoggerFactory;
\r
11 import org.umu.cops.stack.*;
\r
13 import java.io.IOException;
\r
14 import java.net.Socket;
\r
15 import java.util.Date;
\r
16 import java.util.Map;
\r
17 import java.util.concurrent.ConcurrentHashMap;
\r
20 * Class for managing an provisioning connection at the PDP side.
\r
22 public class COPSPdpConnection implements Runnable {
\r
24 public final static Logger logger = LoggerFactory.getLogger(COPSPdpConnection.class);
\r
27 Socket connected to PEP
\r
29 private Socket _sock;
\r
34 private COPSPepId _pepId;
\r
37 Time of the latest keep-alive sent
\r
39 private Date _lastKa;
\r
42 Opcode of the latest message sent
\r
44 private byte _lastmessage;
\r
47 * Time of the latest keep-alive received
\r
49 protected Date _lastRecKa;
\r
52 Maps a Client Handle to a Handler
\r
54 protected final Map<String, COPSPdpReqStateMan> _managerMap;
\r
55 // map < String(COPSHandle), COPSPdpHandler> HandlerMap;
\r
58 * PDP policy data processor class
\r
60 protected COPSPdpDataProcess _process;
\r
63 Accounting timer value (secs)
\r
65 protected short _acctTimer;
\r
68 Keep-alive timer value (secs)
\r
70 protected short _kaTimer;
\r
73 COPS error returned by PEP
\r
75 protected COPSError _error;
\r
78 * Creates a new PDP connection
\r
80 * @param pepId PEP-ID of the connected PEP
\r
81 * @param sock Socket connected to PEP
\r
82 * @param process Object for processing policy data
\r
84 public COPSPdpConnection(COPSPepId pepId, Socket sock, COPSPdpDataProcess process) {
\r
88 _lastKa = new Date();
\r
89 _lastmessage = COPSHeader.COPS_OP_OPN;
\r
90 _managerMap = new ConcurrentHashMap<>();
\r
97 * Gets the time of that latest keep-alive sent
\r
98 * @return Time of that latest keep-alive sent
\r
100 public Date getLastKAlive() {
\r
105 * Sets the keep-alive timer value
\r
106 * @param kaTimer Keep-alive timer value (secs)
\r
108 public void setKaTimer(short kaTimer) {
\r
109 _kaTimer = kaTimer;
\r
113 * Gets the keep-alive timer value
\r
114 * @return Keep-alive timer value (secs)
\r
116 public short getKaTimer() {
\r
121 * Sets the accounting timer value
\r
122 * @param acctTimer Accounting timer value (secs)
\r
124 public void setAccTimer(short acctTimer) {
\r
125 _acctTimer = acctTimer;
\r
129 * Gets the accounting timer value
\r
130 * @return Accounting timer value (secs)
\r
132 public short getAcctTimer() {
\r
137 * Gets the latest COPS message
\r
138 * @return Code of the latest message sent
\r
140 public byte getLastMessage() {
\r
141 return _lastmessage;
\r
146 * @return The ID of the PEP, as a <tt>String</tt>
\r
148 public String getPepId() {
\r
149 return _pepId.getData().str();
\r
153 * Checks whether the socket to the PEP is closed or not
\r
154 * @return <tt>true</tt> if closed, <tt>false</tt> otherwise
\r
156 public boolean isClosed() {
\r
157 return _sock.isClosed();
\r
161 * Closes the socket to the PEP
\r
162 * @throws IOException
\r
164 protected void close()
\r
165 throws IOException {
\r
170 * Gets the socket to the PEP
\r
171 * @return Socket connected to the PEP
\r
173 public Socket getSocket() {
\r
180 public void run () {
\r
181 Date _lastSendKa = new Date();
\r
182 _lastRecKa = new Date();
\r
184 while (!_sock.isClosed()) {
\r
185 if (_sock.getInputStream().available() != 0) {
\r
186 _lastmessage = processMessage(_sock);
\r
187 _lastRecKa = new Date();
\r
191 if (_kaTimer > 0) {
\r
193 int _startTime = (int) (_lastRecKa.getTime());
\r
194 int cTime = (int) (new Date().getTime());
\r
196 if ((cTime - _startTime) > _kaTimer * 1000) {
\r
198 // Notify all Request State Managers
\r
199 notifyNoKAAllReqStateMan();
\r
203 _startTime = (int) (_lastSendKa.getTime());
\r
204 cTime = (int) (new Date().getTime());
\r
206 if ((cTime - _startTime) > ((_kaTimer * 3/4) * 1000)) {
\r
207 COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);
\r
208 COPSKAMsg msg = new COPSKAMsg();
\r
212 COPSTransceiver.sendMsg(msg, _sock);
\r
213 _lastSendKa = new Date();
\r
219 } catch (Exception e) {
\r
220 logger.error("Exception thrown while sleeping", e);
\r
224 } catch (Exception e) {
\r
225 logger.error("Error while processing socket messages", e);
\r
228 // connection closed by server
\r
229 // COPSDebug.out(getClass().getName(),"Connection closed by client");
\r
232 } catch (IOException e) {
\r
233 logger.error("Error closing socket", e);
\r
236 // Notify all Request State Managers
\r
238 notifyCloseAllReqStateMan();
\r
239 } catch (COPSPdpException e) {
\r
240 logger.error("Error closing state managers");
\r
245 * Gets a COPS message from the socket and processes it
\r
246 * @param conn Socket connected to the PEP
\r
247 * @return Type of COPS message
\r
249 private byte processMessage(Socket conn)
\r
250 throws COPSPdpException, COPSException, IOException {
\r
251 COPSMsg msg = COPSTransceiver.receiveMsg(conn);
\r
253 if (msg.getHeader().isAClientClose()) {
\r
254 handleClientCloseMsg(conn, msg);
\r
255 return COPSHeader.COPS_OP_CC;
\r
256 } else if (msg.getHeader().isAKeepAlive()) {
\r
257 handleKeepAliveMsg(conn, msg);
\r
258 return COPSHeader.COPS_OP_KA;
\r
259 } else if (msg.getHeader().isARequest()) {
\r
260 handleRequestMsg(conn, msg);
\r
261 return COPSHeader.COPS_OP_REQ;
\r
262 } else if (msg.getHeader().isAReport()) {
\r
263 handleReportMsg(conn, msg);
\r
264 return COPSHeader.COPS_OP_RPT;
\r
265 } else if (msg.getHeader().isADeleteReq()) {
\r
266 handleDeleteRequestMsg(conn, msg);
\r
267 return COPSHeader.COPS_OP_DRQ;
\r
268 } else if (msg.getHeader().isASyncComplete()) {
\r
269 handleSyncComplete(conn, msg);
\r
270 return COPSHeader.COPS_OP_SSC;
\r
272 throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
\r
277 * Handle Client Close Message, close the passed connection
\r
279 * @param conn a Socket
\r
280 * @param msg a COPSMsg
\r
283 * <Client-Close> ::= <Common Header>
\r
287 * Not support [<Integrity>]
\r
290 private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
\r
291 COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
\r
292 _error = cMsg.getError();
\r
294 // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
\r
295 // conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
\r
299 if (cMsg.getIntegrity() != null) {
\r
300 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
304 } catch (Exception unae) {
\r
305 logger.error("Unexpected exception closing connection", unae);
\r
310 * Gets the occurred COPS Error
\r
311 * @return <tt>COPSError</tt> object
\r
313 protected COPSError getError() {
\r
318 * Handle Keep Alive Message
\r
320 * <Keep-Alive> ::= <Common Header>
\r
323 * Not support [<Integrity>]
\r
325 * @param conn a Socket
\r
326 * @param msg a COPSMsg
\r
329 private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
\r
330 COPSKAMsg cMsg = (COPSKAMsg) msg;
\r
332 COPSKAMsg kaMsg = (COPSKAMsg) msg;
\r
335 if (cMsg.getIntegrity() != null) {
\r
336 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
338 kaMsg.writeData(conn);
\r
339 } catch (Exception unae) {
\r
340 logger.error("Unexpected exception while writing COPS data", unae);
\r
345 * Handle Delete Request Message
\r
347 * <Delete Request> ::= <Common Header>
\r
352 * Not support [<Integrity>]
\r
354 * @param conn a Socket
\r
355 * @param msg a COPSMsg
\r
358 private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)
\r
359 throws COPSPdpException {
\r
360 COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
\r
361 // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +
\r
362 // conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");
\r
365 if (cMsg.getIntegrity() != null) {
\r
366 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
369 // Delete clientHandler
\r
370 if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
\r
371 // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
\r
372 // cMsg.getClientHandle().getId().getData());
\r
375 COPSPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
\r
377 logger.warn("No state manager found with ID - " + cMsg.getClientHandle().getId().str());
\r
379 man.processDeleteRequestState(cMsg);
\r
385 * Handle Request Message
\r
387 * <Request> ::= <Common Header>
\r
390 * *(<Named ClientSI>)
\r
392 * <Named ClientSI> ::= <*(<PRID> <EPD>)>
\r
394 * Not support [<Integrity>]
\r
396 * @param conn a Socket
\r
397 * @param msg a COPSMsg
\r
400 private void handleRequestMsg(Socket conn, COPSMsg msg)
\r
401 throws COPSPdpException {
\r
403 COPSReqMsg reqMsg = (COPSReqMsg) msg;
\r
404 COPSContext cntxt = reqMsg.getContext();
\r
405 COPSHeader header = reqMsg.getHeader();
\r
406 //short reqType = cntxt.getRequestType();
\r
407 short cType = header.getClientType();
\r
410 if (reqMsg.getIntegrity() != null) {
\r
411 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
414 COPSPdpReqStateMan man;
\r
415 man = (COPSPdpReqStateMan) _managerMap.get(reqMsg.getClientHandle().getId().str());
\r
418 man = new COPSPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());
\r
419 _managerMap.put(reqMsg.getClientHandle().getId().str(),man);
\r
420 man.setDataProcess(_process);
\r
421 man.initRequestState(_sock);
\r
423 // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +
\r
424 // header.getClientType() + " msgType=" +
\r
425 // cntxt.getMessageType() + ", connId=" + conn.toString());
\r
428 man.processRequest(reqMsg);
\r
432 * Handle Report Message
\r
434 * <Report State> ::= <Common Header>
\r
437 * *(<Named ClientSI>)
\r
440 * Not support [<Integrity>]
\r
442 * @param conn a Socket
\r
443 * @param msg a COPSMsg
\r
446 private void handleReportMsg(Socket conn, COPSMsg msg)
\r
447 throws COPSPdpException {
\r
448 COPSReportMsg repMsg = (COPSReportMsg) msg;
\r
449 // COPSHandle handle = repMsg.getClientHandle();
\r
450 // COPSHeader header = repMsg.getHeader();
\r
453 if (repMsg.getIntegrity() != null) {
\r
454 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
457 COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());
\r
459 logger.warn("No state manager found with ID - " + repMsg.getClientHandle().getId().str());
\r
461 man.processReport(repMsg);
\r
466 * Method handleSyncComplete
\r
468 * @param conn a Socket
\r
469 * @param msg a COPSMsg
\r
472 private void handleSyncComplete(Socket conn, COPSMsg msg)
\r
473 throws COPSPdpException {
\r
474 COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
\r
475 // COPSHandle handle = cMsg.getClientHandle();
\r
476 // COPSHeader header = cMsg.getHeader();
\r
479 if (cMsg.getIntegrity() != null) {
\r
480 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
483 COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
\r
485 logger.warn("No state manager found with ID - " + cMsg.getClientHandle().getId().str());
\r
487 man.processSyncComplete(cMsg);
\r
492 * Requests a COPS sync from the PEP
\r
493 * @throws COPSException
\r
494 * @throws COPSPdpException
\r
496 protected void syncAllRequestState() throws COPSException, COPSPdpException {
\r
497 for (final COPSPdpReqStateMan man : _managerMap.values()) {
\r
498 man.syncRequestState();
\r
502 private void notifyCloseAllReqStateMan() throws COPSPdpException {
\r
503 for (final COPSPdpReqStateMan man : _managerMap.values()) {
\r
504 man.processClosedConnection(_error);
\r
508 private void notifyNoKAAllReqStateMan() throws COPSPdpException {
\r
509 for (final COPSPdpReqStateMan man : _managerMap.values()) {
\r
510 man.processNoKAConnection();
\r