7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9 import org.umu.cops.prpdp.COPSPdpException;
10 import org.umu.cops.stack.*;
11 import org.umu.cops.stack.COPSHeader.OPCode;
13 import java.io.IOException;
14 import java.net.Socket;
15 import java.util.Date;
16 import java.util.HashMap;
18 import java.util.concurrent.ConcurrentHashMap;
21 * Class for managing an provisioning connection at the PDP side.
23 public class PCMMPdpConnection implements Runnable {
26 public final static Logger logger = LoggerFactory.getLogger(PCMMPdpConnection.class);
29 Socket connected to PEP
36 private COPSPepId _pepId;
39 * Time of the latest keep-alive received
41 protected Date _lastRecKa;
44 Maps a Client Handle to a Handler
46 protected Map<String, PCMMPdpReqStateMan> _managerMap;
49 * PDP policy data processor class
51 protected PCMMPdpDataProcess _process;
54 Accounting timer value (secs)
56 protected short _acctTimer;
59 Keep-alive timer value (secs)
61 protected short _kaTimer;
64 COPS error returned by PEP
66 protected COPSError _error;
69 * Creates a new PDP connection
71 * @param pepId PEP-ID of the connected PEP
72 * @param sock Socket connected to PEP
73 * @param process Object for processing policy data
75 public PCMMPdpConnection(COPSPepId pepId, Socket sock, PCMMPdpDataProcess process) {
78 _managerMap = new ConcurrentHashMap<>();
84 * Sets the keep-alive timer value
85 * @param kaTimer Keep-alive timer value (secs)
87 public void setKaTimer(final short kaTimer) {
92 * Sets the accounting timer value
93 * @param acctTimer Accounting timer value (secs)
95 public void setAccTimer(final short acctTimer) {
96 _acctTimer = acctTimer;
100 * Gets the accounting timer value
101 * @return Accounting timer value (secs)
103 public short getAcctTimer() {
108 * Gets the handle map
109 * @return A <tt>Hashtable</tt> holding the handle map
111 public Map<String, PCMMPdpReqStateMan> getReqStateMans() {
113 return new HashMap<>(_managerMap);
117 * Checks whether the socket to the PEP is closed or not
118 * @return <tt>true</tt> if closed, <tt>false</tt> otherwise
120 public boolean isClosed() {
121 return _sock.isClosed();
125 * Closes the socket to the PEP
126 * @throws IOException
128 protected void close()
134 * Gets the socket to the PEP
135 * @return Socket connected to the PEP
137 public Socket getSocket() {
145 Date _lastSendKa = new Date();
146 _lastRecKa = new Date();
148 while (!_sock.isClosed()) {
149 if (_sock.getInputStream().available() != 0) {
150 processMessage(_sock);
151 _lastRecKa = new Date();
157 int _startTime = (int) (_lastRecKa.getTime());
158 int cTime = (int) (new Date().getTime());
160 if ((cTime - _startTime) > _kaTimer*1000) {
162 // Notify all Request State Managers
163 notifyNoKAAllReqStateMan();
167 _startTime = (int) (_lastSendKa.getTime());
168 cTime = (int) (new Date().getTime());
170 if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
171 // TODO - determine what is the client type to be used here?
172 final COPSKAMsg msg = new COPSKAMsg(null);
173 COPSTransceiver.sendMsg(msg, _sock);
174 _lastSendKa = new Date();
180 } catch (Exception e) {
181 logger.error("Unexpected exception while sleeping", e);
185 } catch (Exception e) {
186 logger.error("Error reading messages from socket", e);
189 // connection closed by server
190 // COPSDebug.out(getClass().getName(),"Connection closed by client");
193 } catch (IOException e) {
194 logger.error("Error closing socket", e);
197 // Notify all Request State Managers
199 notifyCloseAllReqStateMan();
200 } catch (COPSPdpException e) {
201 logger.error("Error closing state managers", e);
206 * Gets a COPS message from the socket and processes it
207 * @param conn Socket connected to the PEP
209 private void processMessage(final Socket conn) throws COPSPdpException, COPSException, IOException {
210 final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
212 if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
213 handleClientCloseMsg(conn, msg);
214 } else if (msg.getHeader().getOpCode().equals(OPCode.KA)) {
215 handleKeepAliveMsg(conn, msg);
216 } else if (msg.getHeader().getOpCode().equals(OPCode.REQ)) {
217 handleRequestMsg(conn, msg);
218 } else if (msg.getHeader().getOpCode().equals(OPCode.RPT)) {
219 handleReportMsg(conn, msg);
220 } else if (msg.getHeader().getOpCode().equals(OPCode.DRQ)) {
221 handleDeleteRequestMsg(conn, msg);
222 } else if (msg.getHeader().getOpCode().equals(OPCode.SSQ)) {
223 handleSyncComplete(conn, msg);
225 throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
230 * Handle Client Close Message, close the passed connection
232 * @param conn a Socket
233 * @param msg a COPSMsg
236 * <Client-Close> ::= <Common Header>
240 * Not support [<Integrity>]
243 private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
244 COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
245 _error = cMsg.getError();
248 if (cMsg.getIntegrity() != null) {
249 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
253 } catch (Exception unae) {
254 logger.error("Unexpected exception closing connection", unae);
259 * Gets the occurred COPS Error
260 * @return <tt>COPSError</tt> object
262 protected COPSError getError() {
267 * Handle Keep Alive Message
269 * <Keep-Alive> ::= <Common Header>
272 * Not support [<Integrity>]
274 * @param conn a Socket
275 * @param msg a COPSMsg
278 private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
279 COPSKAMsg cMsg = (COPSKAMsg) msg;
281 COPSKAMsg kaMsg = (COPSKAMsg) msg;
284 if (cMsg.getIntegrity() != null) {
285 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
288 kaMsg.writeData(conn);
289 } catch (Exception unae) {
290 logger.error("Unexpected exception while writing keep-alive message", unae);
295 * Handle Delete Request Message
297 * <Delete Request> ::= <Common Header>
302 * Not support [<Integrity>]
304 * @param conn a Socket
305 * @param msg a COPSMsg
308 private void handleDeleteRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
309 COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
310 // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +
311 // conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");
314 if (cMsg.getIntegrity() != null) {
315 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
318 // Delete clientHandler
319 if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
320 // TODO - Determine what to do here???
321 // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
322 // cMsg.getClientHandle().getId().getData());
325 final PCMMPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
327 logger.warn("State manager not found");
329 man.processDeleteRequestState(cMsg);
335 * Handle Request Message
337 * <Request> ::= <Common Header>
340 * *(<Named ClientSI>)
342 * <Named ClientSI> ::= <*(<PRID> <EPD>)>
344 * Not support [<Integrity>]
346 * @param conn a Socket
347 * @param msg a COPSMsg
350 private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
352 final COPSReqMsg reqMsg = (COPSReqMsg) msg;
353 // COPSContext cntxt = reqMsg.getContext();
354 final COPSHeader header = reqMsg.getHeader();
355 //short reqType = cntxt.getRequestType();
356 final short cType = header.getClientType();
359 if (reqMsg.getIntegrity() != null) {
360 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
363 PCMMPdpReqStateMan man;
364 man = _managerMap.get(reqMsg.getClientHandle().getId().str());
367 man = new PCMMPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());
368 _managerMap.put(reqMsg.getClientHandle().getId().str(), man);
369 man.setDataProcess(_process);
370 man.initRequestState(_sock);
372 // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +
373 // header.getClientType() + " msgType=" +
374 // cntxt.getMessageType() + ", connId=" + conn.toString());
377 man.processRequest(reqMsg);
381 * Handle Report Message
383 * <Report State> ::= <Common Header>
386 * *(<Named ClientSI>)
389 * Not support [<Integrity>]
391 * @param conn a Socket
392 * @param msg a COPSMsg
395 private void handleReportMsg(Socket conn, COPSMsg msg)
396 throws COPSPdpException {
397 COPSReportMsg repMsg = (COPSReportMsg) msg;
398 // COPSHandle handle = repMsg.getClientHandle();
399 // COPSHeader header = repMsg.getHeader();
402 if (repMsg.getIntegrity() != null) {
403 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
406 final PCMMPdpReqStateMan man = _managerMap.get(repMsg.getClientHandle().getId().str());
408 logger.warn("State manager not found");
410 man.processReport(repMsg);
415 * Method handleSyncComplete
417 * @param conn a Socket
418 * @param msg a COPSMsg
421 private void handleSyncComplete(Socket conn, COPSMsg msg)
422 throws COPSPdpException {
423 COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
424 // COPSHandle handle = cMsg.getClientHandle();
425 // COPSHeader header = cMsg.getHeader();
428 if (cMsg.getIntegrity() != null) {
429 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
432 final PCMMPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
434 logger.warn("State manager not found");
436 man.processSyncComplete(cMsg);
441 * Requests a COPS sync from the PEP
442 * @throws COPSException
443 * @throws COPSPdpException
445 protected void syncAllRequestState() throws COPSException, COPSPdpException {
446 for (final PCMMPdpReqStateMan man : _managerMap.values()) {
447 man.syncRequestState();
451 private void notifyCloseAllReqStateMan() throws COPSPdpException {
452 for (final PCMMPdpReqStateMan man : _managerMap.values()) {
453 man.processClosedConnection(_error);
457 private void notifyNoKAAllReqStateMan() throws COPSPdpException {
458 for (final PCMMPdpReqStateMan man : _managerMap.values()) {
459 man.processNoKAConnection();