7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9 import org.umu.cops.prpdp.COPSPdpException;
10 import org.umu.cops.stack.*;
12 import javax.annotation.concurrent.ThreadSafe;
13 import java.io.IOException;
14 import java.net.Socket;
15 import java.util.Date;
17 import java.util.concurrent.ConcurrentHashMap;
20 * Class for managing an provisioning connection at the PDP side for receiving and brokering out COPS messages.
23 public class PCMMPdpConnection implements Runnable {
25 private final static Logger logger = LoggerFactory.getLogger(PCMMPdpConnection.class);
28 Socket connected to PEP
30 private final Socket _sock;
34 * TODO - Determine why the original author put this object into this class
36 private final COPSPepId _pepId;
39 * Time of the latest keep-alive received
41 protected Date _lastRecKa;
44 * Maps a Client Handle to a Handler
46 protected final Map<String, PCMMPdpReqStateMan> _managerMap;
49 * PDP policy data processor class
51 protected final PCMMPdpDataProcess _process;
54 * Accounting timer value (secs)
56 protected final short _acctTimer;
59 * Keep-alive timer value (secs)
61 protected final short _kaTimer;
64 * COPS error returned by PEP on close
66 protected transient 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(final COPSPepId pepId, final Socket sock, final PCMMPdpDataProcess process,
76 final short kaTimer, final short acctTimer) {
81 _acctTimer = acctTimer;
82 _managerMap = new ConcurrentHashMap<>();
85 public void addStateMan(final String key, final PCMMPdpReqStateMan man) {
86 _managerMap.put(key, man);
90 * Checks whether the socket to the PEP is closed or not
91 * @return <tt>true</tt> if closed, <tt>false</tt> otherwise
93 public boolean isClosed() {
94 return _sock.isClosed();
98 * Closes the socket to the PEP
101 protected void close() throws IOException {
102 if (!_sock.isClosed()) _sock.close();
106 * Gets the socket to the PEP
107 * @return Socket connected to the PEP
109 public Socket getSocket() {
117 logger.info("Starting socket listener.");
118 Date _lastSendKa = new Date();
119 _lastRecKa = new Date();
121 // Loop while socket is open
122 while (!_sock.isClosed()) {
124 if (_sock.getInputStream().available() != 0) {
125 logger.info("Waiting to process socket messages");
126 processMessage(_sock);
127 logger.info("Message processed");
128 _lastRecKa = new Date();
134 int _startTime = (int) (_lastRecKa.getTime());
135 int cTime = (int) (new Date().getTime());
137 if ((cTime - _startTime) > _kaTimer*1000) {
139 // Notify all Request State Managers
140 notifyNoKAAllReqStateMan();
144 _startTime = (int) (_lastSendKa.getTime());
145 cTime = (int) (new Date().getTime());
147 if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
148 final COPSKAMsg msg = new COPSKAMsg(null);
149 logger.info("Sending KA message to CCAP");
150 COPSTransceiver.sendMsg(msg, _sock);
151 logger.info("Sent KA message gto CCAP");
152 _lastSendKa = new Date();
158 } catch (InterruptedException e) {
159 logger.info("Shutting down socket connection to CCAP");
162 } catch (IOException e) {
163 logger.error("Exception reading from socket - exiting", e);
165 } catch (COPSException e) {
166 logger.error("Exception processing message - continue processing", e);
171 if (! _sock.isClosed())
173 } catch (IOException e) {
174 logger.error("Error closing socket", e);
177 // Notify all Request State Managers
179 notifyCloseAllReqStateMan();
180 } catch (COPSPdpException e) {
181 logger.error("Error closing state managers", e);
186 * Gets a COPS message from the socket and processes it
187 * @param conn Socket connected to the PEP
189 private void processMessage(final Socket conn) throws COPSException, IOException {
190 final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
192 logger.info("Processing message received of type - " + msg.getHeader().getOpCode());
194 switch (msg.getHeader().getOpCode()) {
196 handleClientCloseMsg(conn, (COPSClientCloseMsg)msg);
199 handleKeepAliveMsg(conn, (COPSKAMsg)msg);
202 handleRequestMsg(conn, (COPSReqMsg)msg);
205 handleReportMsg(conn, (COPSReportMsg)msg);
208 handleDeleteRequestMsg(conn, (COPSDeleteMsg)msg);
211 handleSyncComplete(conn, (COPSSyncStateMsg)msg);
214 throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
219 * Handle Client Close Message, close the passed connection
220 * @param conn a Socket
221 * @param cMsg a COPSClientCloseMsg
223 private void handleClientCloseMsg(final Socket conn, final COPSClientCloseMsg cMsg) {
224 _error = cMsg.getError();
225 logger.info("Closing client with error - " + _error.getDescription());
228 if (cMsg.getIntegrity() != null) {
229 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
233 } catch (Exception unae) {
234 logger.error("Unexpected exception closing connection", unae);
239 * Handle Keep Alive Message
240 * @param conn a Socket
241 * @param kaMsg a COPSKAMsg
243 private void handleKeepAliveMsg(final Socket conn, final COPSKAMsg kaMsg) {
246 if (kaMsg.getIntegrity() != null) {
247 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
249 kaMsg.writeData(conn);
250 } catch (Exception unae) {
251 logger.error("Unexpected exception while writing keep-alive message", unae);
256 * Handle Delete Request Message
257 * @param conn a Socket
258 * @param cMsg a COPSDeleteMsg
260 private void handleDeleteRequestMsg(final Socket conn, final COPSDeleteMsg cMsg) throws COPSPdpException {
262 if (cMsg.getIntegrity() != null) {
263 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
266 // Delete clientHandler
267 final PCMMPdpReqStateMan man = _managerMap.remove(cMsg.getClientHandle().getId().str());
269 logger.warn("Cannot delete request state, no state manger found");
271 man.processDeleteRequestState(cMsg);
276 * Handle Request Message
277 * @param conn a Socket
278 * @param reqMsg a COPSReqMsg
280 private void handleRequestMsg(final Socket conn, final COPSReqMsg reqMsg) throws COPSException {
281 final COPSHeader header = reqMsg.getHeader();
282 final short cType = header.getClientType();
285 if (reqMsg.getIntegrity() != null) {
286 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
289 final PCMMPdpReqStateMan man;
290 if (_managerMap.get(reqMsg.getClientHandle().getId().str()) == null) {
292 man = new PCMMPdpReqStateMan(cType, reqMsg.getClientHandle(), _process);
293 _managerMap.put(reqMsg.getClientHandle().getId().str(), man);
294 man.initRequestState(_sock);
295 logger.info("Created state manager for ID - " + reqMsg.getClientHandle().getId().str());
297 man = _managerMap.get(reqMsg.getClientHandle().getId().str());
300 man.processRequest(reqMsg);
304 * Handle Report Message
305 * @param conn a Socket
306 * @param repMsg a COPSReportMsg
308 private void handleReportMsg(final Socket conn, final COPSReportMsg repMsg) throws COPSPdpException {
310 if (repMsg.getIntegrity() != null) {
311 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
314 final PCMMPdpReqStateMan man = _managerMap.get(repMsg.getClientHandle().getId().str());
316 logger.warn("State manager not found");
318 man.processReport(repMsg);
323 * Method handleSyncComplete
324 * @param conn a Socket
325 * @param cMsg a COPSSyncStateMsg
327 private void handleSyncComplete(final Socket conn, final COPSSyncStateMsg cMsg) throws COPSException {
329 if (cMsg.getIntegrity() != null) {
330 logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
333 final PCMMPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
335 logger.warn("State manager not found");
337 man.processSyncComplete(cMsg);
342 * Requests a COPS sync from the PEP
343 * @throws COPSException
344 * @throws COPSPdpException
346 protected void syncAllRequestState() throws COPSException {
347 for (final PCMMPdpReqStateMan man : _managerMap.values()) {
348 man.syncRequestState();
352 private void notifyCloseAllReqStateMan() throws COPSPdpException {
353 for (final PCMMPdpReqStateMan man : _managerMap.values()) {
354 man.processClosedConnection(_error);
358 private void notifyNoKAAllReqStateMan() throws COPSPdpException {
359 for (final PCMMPdpReqStateMan man : _managerMap.values()) {
360 man.processNoKAConnection();