1 package org.umu.cops.ospdp;
\r
3 import org.slf4j.Logger;
\r
4 import org.slf4j.LoggerFactory;
\r
5 import org.umu.cops.stack.*;
\r
7 import java.io.IOException;
\r
8 import java.net.Socket;
\r
9 import java.util.Date;
\r
10 import java.util.Enumeration;
\r
11 import java.util.Hashtable;
\r
14 * Class for managing an outsourcing connection at the PDP side.
\r
16 public class COPSPdpOSConnection implements Runnable {
\r
18 public final static Logger logger = LoggerFactory.getLogger(COPSPdpOSConnection.class);
\r
21 Socket connected to PEP
\r
23 private Socket _sock;
\r
28 private COPSPepId _pepId;
\r
31 Time of the latest keep-alive sent
\r
33 private Date _lastKa;
\r
36 Opcode of the latest message sent
\r
38 private byte _lastmessage;
\r
41 * Time of the latest keep-alive received
\r
43 protected Date _lastRecKa;
\r
46 Maps a Client Handle to a Handler
\r
48 protected Hashtable _managerMap;
\r
49 // map < String(COPSHandle), COPSPdpHandler> HandlerMap;
\r
52 * PDP policy data processor class
\r
54 protected COPSPdpOSDataProcess _process;
\r
57 Accounting timer value (secs)
\r
59 protected short _acctTimer;
\r
62 Keep-alive timer value (secs)
\r
64 protected short _kaTimer;
\r
67 COPS error returned by PEP
\r
69 protected COPSError _error;
\r
72 * Creates a new PDP connection
\r
74 * @param pepId PEP-ID of the connected PEP
\r
75 * @param sock Socket connected to PEP
\r
76 * @param process Object for processing policy data
\r
78 public COPSPdpOSConnection(COPSPepId pepId, Socket sock, COPSPdpOSDataProcess process) {
\r
82 _lastKa = new Date();
\r
83 _lastmessage = COPSHeader.COPS_OP_OPN;
\r
84 _managerMap = new Hashtable(20);
\r
91 * Gets the time of that latest keep-alive sent
\r
92 * @return Time of that latest keep-alive sent
\r
94 public Date getLastKAlive() {
\r
99 * Sets the keep-alive timer value
\r
100 * @param kaTimer Keep-alive timer value (secs)
\r
102 public void setKaTimer(short kaTimer) {
\r
103 _kaTimer = kaTimer;
\r
107 * Gets the keep-alive timer value
\r
108 * @return Keep-alive timer value (secs)
\r
110 public short getKaTimer() {
\r
115 * Sets the accounting timer value
\r
116 * @param acctTimer Accounting timer value (secs)
\r
118 public void setAccTimer(short acctTimer) {
\r
119 _acctTimer = acctTimer;
\r
123 * Gets the accounting timer value
\r
124 * @return Accounting timer value (secs)
\r
126 public short getAcctTimer() {
\r
131 * Gets the latest COPS message
\r
132 * @return Code of the latest message sent
\r
134 public byte getLastMessage() {
\r
135 return _lastmessage;
\r
139 * Gets active handles
\r
140 * @return An <tt>Enumeration</tt> holding all active handles
\r
142 public Enumeration getHandles() {
\r
143 return _managerMap.keys();
\r
147 * Gets the handle map
\r
148 * @return A <tt>Hashtable</tt> holding the handle map
\r
150 public Hashtable getReqStateMans() {
\r
151 return _managerMap;
\r
156 * @return The ID of the PEP, as a <tt>String</tt>
\r
158 public String getPepId() {
\r
159 return _pepId.getData().str();
\r
163 * Checks whether the socket to the PEP is closed or not
\r
164 * @return <tt>true</tt> if closed, <tt>false</tt> otherwise
\r
166 public boolean isClosed() {
\r
167 return _sock.isClosed();
\r
171 * Closes the socket to the PEP
\r
172 * @throws IOException
\r
174 protected void close()
\r
175 throws IOException {
\r
180 * Gets the socket to the PEP
\r
181 * @return Socket connected to the PEP
\r
183 public Socket getSocket() {
\r
190 public void run () {
\r
191 Date _lastSendKa = new Date();
\r
192 _lastRecKa = new Date();
\r
194 while (!_sock.isClosed()) {
\r
195 if (_sock.getInputStream().available() != 0) {
\r
196 _lastmessage = processMessage(_sock);
\r
197 _lastRecKa = new Date();
\r
201 if (_kaTimer > 0) {
\r
203 int _startTime = (int) (_lastRecKa.getTime());
\r
204 int cTime = (int) (new Date().getTime());
\r
206 if ((cTime - _startTime) > _kaTimer*1000) {
\r
208 // Notify all Request State Managers
\r
209 notifyNoKAAllReqStateMan();
\r
213 _startTime = (int) (_lastSendKa.getTime());
\r
214 cTime = (int) (new Date().getTime());
\r
216 if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
\r
217 COPSHeader hdr = new COPSHeader(COPSHeader.COPS_OP_KA);
\r
218 COPSKAMsg msg = new COPSKAMsg();
\r
222 COPSTransceiver.sendMsg(msg, _sock);
\r
223 _lastSendKa = new Date();
\r
229 } catch (Exception e) {
\r
230 logger.error("Exception caught while sleeping", e);
\r
234 } catch (Exception e) {
\r
235 logger.error("Error processing COPS message from socket", e);
\r
238 // connection closed by server
\r
239 // COPSDebug.out(getClass().getName(),"Connection closed by client");
\r
242 } catch (IOException e) {
\r
243 logger.error("Error closing socket", e);
\r
246 // Notify all Request State Managers
\r
248 notifyCloseAllReqStateMan();
\r
249 } catch (COPSPdpException e) {
\r
250 logger.error("Error closing state managers", e);
\r
255 * Gets a COPS message from the socket and processes it
\r
256 * @param conn Socket connected to the PEP
\r
257 * @return Type of COPS message
\r
259 private byte processMessage(Socket conn)
\r
260 throws COPSPdpException, COPSException, IOException {
\r
261 COPSMsg msg = COPSTransceiver.receiveMsg(conn);
\r
263 if (msg.getHeader().isAClientClose()) {
\r
264 handleClientCloseMsg(conn, msg);
\r
265 return COPSHeader.COPS_OP_CC;
\r
266 } else if (msg.getHeader().isAKeepAlive()) {
\r
267 handleKeepAliveMsg(conn, msg);
\r
268 return COPSHeader.COPS_OP_KA;
\r
269 } else if (msg.getHeader().isARequest()) {
\r
270 handleRequestMsg(conn, msg);
\r
271 return COPSHeader.COPS_OP_REQ;
\r
272 } else if (msg.getHeader().isAReport()) {
\r
273 handleReportMsg(conn, msg);
\r
274 return COPSHeader.COPS_OP_RPT;
\r
275 } else if (msg.getHeader().isADeleteReq()) {
\r
276 handleDeleteRequestMsg(conn, msg);
\r
277 return COPSHeader.COPS_OP_DRQ;
\r
278 } else if (msg.getHeader().isASyncComplete()) {
\r
279 handleSyncComplete(conn, msg);
\r
280 return COPSHeader.COPS_OP_SSC;
\r
282 throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
\r
287 * Handle Client Close Message, close the passed connection
\r
289 * @param conn a Socket
\r
290 * @param msg a COPSMsg
\r
293 * <Client-Close> ::= <Common Header>
\r
297 * Not support [<Integrity>]
\r
300 private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
\r
301 COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
\r
302 _error = cMsg.getError();
\r
304 // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
\r
305 // conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
\r
309 if (cMsg.getIntegrity() != null) {
\r
310 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
314 } catch (Exception unae) {
\r
315 logger.error("Unexpected exception while closing the connection", unae);
\r
320 * Gets the occurred COPS Error
\r
321 * @return <tt>COPSError</tt> object
\r
323 protected COPSError getError() {
\r
328 * Handle Keep Alive Message
\r
330 * <Keep-Alive> ::= <Common Header>
\r
333 * Not support [<Integrity>]
\r
335 * @param conn a Socket
\r
336 * @param msg a COPSMsg
\r
339 private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
\r
340 COPSKAMsg cMsg = (COPSKAMsg) msg;
\r
342 COPSKAMsg kaMsg = (COPSKAMsg) msg;
\r
345 if (cMsg.getIntegrity() != null) {
\r
346 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
349 kaMsg.writeData(conn);
\r
350 } catch (Exception unae) {
\r
351 logger.error("Unexpected exception writing COPS data", unae);
\r
356 * Handle Delete Request Message
\r
358 * <Delete Request> ::= <Common Header>
\r
363 * Not support [<Integrity>]
\r
365 * @param conn a Socket
\r
366 * @param msg a COPSMsg
\r
369 private void handleDeleteRequestMsg(Socket conn, COPSMsg msg)
\r
370 throws COPSPdpException {
\r
371 COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
\r
372 // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +
\r
373 // conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");
\r
376 if (cMsg.getIntegrity() != null) {
\r
377 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
380 // Delete clientHandler
\r
381 if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
\r
382 // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
\r
383 // cMsg.getClientHandle().getId().getData());
\r
386 COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
\r
388 logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());
\r
390 man.processDeleteRequestState(cMsg);
\r
396 * Handle Request Message
\r
398 * <Request> ::= <Common Header>
\r
401 * *(<Named ClientSI>)
\r
403 * <Named ClientSI> ::= <*(<PRID> <EPD>)>
\r
405 * Not support [<Integrity>]
\r
407 * @param conn a Socket
\r
408 * @param msg a COPSMsg
\r
411 private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
\r
412 COPSReqMsg reqMsg = (COPSReqMsg) msg;
\r
413 COPSContext cntxt = reqMsg.getContext();
\r
414 COPSHeader header = reqMsg.getHeader();
\r
415 //short reqType = cntxt.getRequestType();
\r
416 short cType = header.getClientType();
\r
419 if (reqMsg.getIntegrity() != null) {
\r
420 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
423 COPSPdpOSReqStateMan man;
\r
424 man = (COPSPdpOSReqStateMan) _managerMap.get(reqMsg.getClientHandle().getId().str());
\r
426 man = new COPSPdpOSReqStateMan(cType, reqMsg.getClientHandle().getId().str());
\r
427 _managerMap.put(reqMsg.getClientHandle().getId().str(),man);
\r
428 man.setDataProcess(_process);
\r
429 man.initRequestState(_sock);
\r
431 // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +
\r
432 // header.getClientType() + " msgType=" +
\r
433 // cntxt.getMessageType() + ", connId=" + conn.toString());
\r
436 man.processRequest(reqMsg);
\r
440 * Handle Report Message
\r
442 * <Report State> ::= <Common Header>
\r
445 * *(<Named ClientSI>)
\r
448 * Not support [<Integrity>]
\r
450 * @param conn a Socket
\r
451 * @param msg a COPSMsg
\r
454 private void handleReportMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
\r
455 COPSReportMsg repMsg = (COPSReportMsg) msg;
\r
456 // COPSHandle handle = repMsg.getClientHandle();
\r
457 // COPSHeader header = repMsg.getHeader();
\r
460 if (repMsg.getIntegrity() != null) {
\r
461 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
464 COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(repMsg.getClientHandle().getId().str());
\r
466 logger.warn("State manager not found for ID - " + repMsg.getClientHandle().getId().str());
\r
468 man.processReport(repMsg);
\r
473 * Method handleSyncComplete
\r
475 * @param conn a Socket
\r
476 * @param msg a COPSMsg
\r
479 private void handleSyncComplete(Socket conn, COPSMsg msg)
\r
480 throws COPSPdpException {
\r
481 COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
\r
482 // COPSHandle handle = cMsg.getClientHandle();
\r
483 // COPSHeader header = cMsg.getHeader();
\r
486 if (cMsg.getIntegrity() != null) {
\r
487 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
\r
490 COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
\r
492 logger.warn("State manager not found for ID - " + cMsg.getClientHandle().getId().str());
\r
494 man.processSyncComplete(cMsg);
\r
499 * Requests a COPS sync from the PEP
\r
500 * @throws COPSException
\r
501 * @throws COPSPdpException
\r
503 protected void syncAllRequestState()
\r
504 throws COPSException, COPSPdpException {
\r
505 if (_managerMap.size() > 0) {
\r
506 for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {
\r
507 String handle = (String) e.nextElement();
\r
508 COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(handle);
\r
510 man.syncRequestState();
\r
515 private void notifyCloseAllReqStateMan()
\r
516 throws COPSPdpException {
\r
517 if (_managerMap.size() > 0) {
\r
518 for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {
\r
519 String handle = (String) e.nextElement();
\r
520 COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(handle);
\r
522 man.processClosedConnection(_error);
\r
527 private void notifyNoKAAllReqStateMan()
\r
528 throws COPSPdpException {
\r
529 if (_managerMap.size() > 0) {
\r
530 for (Enumeration e = _managerMap.keys() ; e.hasMoreElements() ;) {
\r
531 String handle = (String) e.nextElement();
\r
532 COPSPdpOSReqStateMan man = (COPSPdpOSReqStateMan) _managerMap.get(handle);
\r
534 man.processNoKAConnection();
\r