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.prpep;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11 import org.umu.cops.stack.*;
12 import org.umu.cops.stack.COPSDecision.Command;
13 import org.umu.cops.stack.COPSDecision.DecisionFlag;
14 import org.umu.cops.stack.COPSHeader.OPCode;
16 import java.io.IOException;
17 import java.net.Socket;
18 import java.util.Date;
21 import java.util.concurrent.ConcurrentHashMap;
24 * COPSPepConnection represents a PEP-PDP Connection Manager.
25 * Responsible for processing messages received from PDP.
27 public class COPSPepConnection implements Runnable {
29 public final static Logger logger = LoggerFactory.getLogger(COPSPepConnection.class);
31 /** Socket connected to PDP */
32 protected Socket _sock;
34 /** Time to wait responses (milliseconds), default is 10 seconds */
35 protected int _responseTime;
37 /** COPS Client-type */
38 protected short _clientType;
41 Accounting timer value (secs)
43 protected short _acctTimer;
46 Keep-alive timer value (secs)
48 protected short _kaTimer;
51 * Time of the latest keep-alive received
53 protected Date _lastRecKa;
56 Maps a COPS Client Handle to a Request State Manager
58 protected final Map<String, COPSPepReqStateMan> _managerMap;
61 COPS error returned by PDP
63 protected COPSError _error;
66 * Creates a new PEP connection
67 * @param clientType PEP's client-type
68 * @param sock Socket connected to PDP
70 public COPSPepConnection(final short clientType, final Socket sock) {
72 _clientType = clientType;
78 _responseTime = 10000;
79 _managerMap = new ConcurrentHashMap<>();
83 * Gets the response time
84 * @return Response time value (msecs)
86 public int getResponseTime() {
91 * Gets the socket connected to the PDP
92 * @return Socket connected to PDP
94 public Socket getSocket() {
99 * Gets keep-alive timer
100 * @return Keep-alive timer value (secs)
102 public short getKaTimer () {
107 * Gets accounting timer
108 * @return Accounting timer value (secs)
110 public short getAcctTimer () {
115 * Checks whether the socket to the PDP is closed or not
116 * @return <tt>true</tt> if the socket is closed, <tt>false</tt> otherwise
118 public boolean isClosed() {
119 return _sock.isClosed();
125 * @throws java.io.IOException
127 protected void close()
134 * @param respTime Response time value (msecs)
136 public void setResponseTime(int respTime) {
137 _responseTime = respTime;
141 * Sets keep-alive timer
142 * @param kaTimer Keep-alive timer value (secs)
144 public void setKaTimer (short kaTimer) {
149 * Sets accounting timer
150 * @param acctTimer Accounting timer value (secs)
152 public void setAcctTimer (short acctTimer) {
153 _acctTimer = acctTimer;
157 * Message-processing loop
160 Date _lastSendKa = new Date();
161 Date _lastSendAcc = new Date();
162 _lastRecKa = new Date();
164 while (!_sock.isClosed()) {
165 if (_sock.getInputStream().available() != 0) {
166 processMessage(_sock);
167 _lastRecKa = new Date();
173 int _startTime = (int) (_lastRecKa.getTime());
174 int cTime = (int) (new Date().getTime());
176 if ((cTime - _startTime) > _kaTimer*1000) {
178 // Notify all Request State Managers
179 notifyNoKAAllReqStateMan();
183 _startTime = (int) (_lastSendKa.getTime());
184 cTime = (int) (new Date().getTime());
186 if ((cTime - _startTime) > ((_kaTimer*3/4) * 1000)) {
187 final COPSKAMsg msg = new COPSKAMsg(null);
188 COPSTransceiver.sendMsg(msg, _sock);
189 _lastSendKa = new Date();
194 if (_acctTimer > 0) {
195 int _startTime = (int) (_lastSendAcc.getTime());
196 int cTime = (int) (new Date().getTime());
198 if ((cTime - _startTime) > ((_acctTimer*3/4)*1000)) {
199 // Notify all Request State Managers
200 notifyAcctAllReqStateMan();
201 _lastSendAcc = new Date();
207 } catch (Exception e) {
208 logger.error("Exception thrown while sleeping", e);
211 } catch (Exception e) {
212 logger.error("Error while processing socket messages", e);
215 // connection closed by server
216 // COPSDebug.out(getClass().getName(),"Connection closed by server");
219 } catch (IOException e) {
220 logger.error("Error closing socket", e);
223 // Notify all Request State Managers
225 notifyCloseAllReqStateMan();
226 } catch (COPSPepException e) {
227 logger.error("Error closing state managers");
232 * Gets a COPS message from the socket and processes it
233 * @param conn Socket connected to the PDP
234 * @return COPS message type
235 * @throws COPSPepException
236 * @throws COPSException
237 * @throws IOException
239 protected byte processMessage(final Socket conn) throws COPSPepException, COPSException, IOException {
240 final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
242 switch (msg.getHeader().getOpCode()) {
244 handleClientCloseMsg(conn, msg);
245 return (byte)OPCode.CC.ordinal();
247 handleDecisionMsg(conn, msg);
248 return (byte)OPCode.DEC.ordinal();
250 handleSyncStateReqMsg(conn, msg);
251 return (byte)OPCode.SSQ.ordinal();
253 handleKeepAliveMsg(conn, msg);
254 return (byte)OPCode.KA.ordinal();
256 throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");
261 * Handle Client Close Message, close the passed connection
263 * @param conn a Socket
264 * @param msg a COPSMsg
267 * <Client-Close> ::= <Common Header>
271 * Not support [<Integrity>]
274 private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
275 COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
276 _error = cMsg.getError();
278 // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
279 // conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
283 if (cMsg.getIntegrity() != null) {
284 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
288 } catch (Exception unae) {
289 logger.error("Unexpected exception closing connection", unae);
296 * @return a COPSError
299 protected COPSError getError() {
304 * Handle Keep Alive Message
306 * <Keep-Alive> ::= <Common Header>
309 * Not support [<Integrity>]
311 * @param conn a Socket
312 * @param msg a COPSMsg
315 private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
316 COPSKAMsg cMsg = (COPSKAMsg) msg;
318 // COPSDebug.out(getClass().getName(),"Get KAlive Msg");
322 if (cMsg.getIntegrity() != null) {
323 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
326 // should we do anything else?? ....
328 } catch (Exception unae) {
329 logger.error("Unexpected exception while writing COPS data", unae);
334 * Method handleDecisionMsg
336 * <Decision Message> ::= <Common Header: Flag SOLICITED>
338 * *(<Decision>) | <Error>
340 * <Decision> ::= <Context>
342 * [<Named Decision Data: Provisioning>]
343 * <Decision: Flags> ::= <Command-Code> NULLFlag
344 * <Command-Code> ::= NULLDecision | Install | Remove
345 * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>
346 * <Install Decision> ::= *(<PRID> <EPD>)
347 * <Remove Decision> ::= *(<PRID> | <PPRID>)
349 * Very important, this is actually being treated like this:
350 * <Install Decision> ::= <PRID> | <EPD>
351 * <Remove Decision> ::= <PRID> | <PPRID>
353 * @param conn a Socket
354 * @param msg a COPSMsg
357 private void handleDecisionMsg(final Socket conn, final COPSMsg msg) throws COPSPepException {
358 final COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
359 final COPSHandle handle = dMsg.getClientHandle();
360 final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
362 for (final Set<COPSDecision> copsDecisions: decisions.values()) {
363 for (final COPSDecision decision : copsDecisions) {
364 // Get the associated manager
365 final COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
367 logger.warn("Unable to find state manager with key - " + handle.getId().str());
369 // Check message type
370 // TODO FIXME - Use of manager object could result in a NPE
371 if (decision.getFlag().equals(DecisionFlag.REQSTATE)) {
372 if (decision.getCommand().equals(Command.REMOVE))
373 // Delete Request State
374 manager.processDeleteRequestState(dMsg);
376 // Open new Request State
377 handleOpenNewRequestStateMsg(conn, handle);
380 manager.processDecision(dMsg);
387 * Method handleOpenNewRequestStateMsg
389 * @param conn a Socket
390 * @param handle a COPSHandle
393 private void handleOpenNewRequestStateMsg(Socket conn, COPSHandle handle) throws COPSPepException {
395 COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
397 logger.warn("Unable to find state manager with key - " + handle.getId().str());
399 // TODO FIXME - Use of manager object could result in a NPE
400 manager.processOpenNewRequestState();
404 * Method handleSyncStateReqMsg
406 * <Synchronize State> ::= <Common Header>
410 * @param conn a Socket
411 * @param msg a COPSMsg
414 private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {
415 COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
418 if (cMsg.getIntegrity() != null) {
419 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
422 COPSPepReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
423 if (manager == null) {
424 logger.warn("Unable to find state manager with key - " + cMsg.getClientHandle().getId().str());
426 manager.processSyncStateRequest(cMsg);
431 * Method createRequestState
433 * @param clientHandle a String
434 * @param process a COPSPepDataProcess
436 * @return a COPSPepmanager
438 * @throws COPSException
439 * @throws COPSPepException
442 protected COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process) throws COPSException,
444 COPSPepReqStateMan manager = new COPSPepReqStateMan(_clientType, clientHandle);
445 if (_managerMap.get(clientHandle) != null)
446 throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);
448 manager.setDataProcess(process);
449 _managerMap.put(clientHandle,manager);
450 manager.initRequestState(_sock);
455 * Method deleteRequestState
457 * @param manager a COPSPepReqStateMan
459 * @throws COPSException
460 * @throws COPSPepException
463 protected void deleteRequestState(COPSPepReqStateMan manager) throws COPSException, COPSPepException {
464 manager.finalizeRequestState();
467 private void notifyCloseAllReqStateMan() throws COPSPepException {
468 for (final COPSPepReqStateMan man: _managerMap.values()) {
469 man.processClosedConnection(_error);
473 private void notifyNoKAAllReqStateMan() throws COPSPepException {
474 for (final COPSPepReqStateMan man: _managerMap.values()) {
475 man.processNoKAConnection();
479 private void notifyAcctAllReqStateMan() throws COPSPepException {
480 for (final COPSPepReqStateMan man: _managerMap.values()) {
481 man.processAcctReport();