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.ServerSocket;
\r
15 import java.net.Socket;
\r
16 import java.util.Hashtable;
\r
17 import java.util.Map;
\r
18 import java.util.concurrent.ConcurrentHashMap;
\r
21 * Core PDP agent for provisioning
\r
23 public class COPSPdpAgent extends Thread {
\r
25 public final static Logger logger = LoggerFactory.getLogger(COPSPdpAgent.class);
\r
27 /** Well-known port for COPS */
\r
28 public static final int WELL_KNOWN_PDP_PORT = 3288;
\r
29 /** Default keep-alive timer value (secs) */
\r
30 public static final short KA_TIMER_VALUE = 30;
\r
31 /** Default accounting timer value (secs) */
\r
32 public static final short ACCT_TIMER_VALUE = 0;
\r
37 private int _serverPort;
\r
40 Client-type of connecting PEP
\r
42 private short _clientType;
\r
45 Accounting timer (secs)
\r
47 private short _acctTimer;
\r
50 Keep-alive timer (secs)
\r
52 private short _kaTimer;
\r
55 Maps a PEP-ID to a connection
\r
57 private final Map<String, COPSPdpConnection> _connectionMap;
\r
58 // map < String(PEPID), COPSPdpConnection > ConnectionMap;
\r
61 * Policy data processing object
\r
63 private COPSPdpDataProcess _process;
\r
66 * Creates a PDP Agent
\r
68 * @param clientType COPS Client-type
\r
69 * @param process Object to perform policy data processing
\r
71 public COPSPdpAgent(short clientType, COPSPdpDataProcess process) {
\r
72 _serverPort = WELL_KNOWN_PDP_PORT;
\r
73 _kaTimer = KA_TIMER_VALUE;
\r
74 _acctTimer = ACCT_TIMER_VALUE;
\r
76 _clientType = clientType;
\r
77 _connectionMap = new ConcurrentHashMap<>();
\r
82 * Creates a PDP Agent
\r
84 * @param port Port to listen to
\r
85 * @param clientType COPS Client-type
\r
86 * @param process Object to perform policy data processing
\r
88 public COPSPdpAgent(int port, short clientType, COPSPdpDataProcess process) {
\r
91 _kaTimer = KA_TIMER_VALUE;
\r
92 _acctTimer = ACCT_TIMER_VALUE;
\r
94 _clientType = clientType;
\r
95 _connectionMap = new ConcurrentHashMap<>();
\r
100 * Sets the keep-alive timer value
\r
101 * @param kaTimer Keep alive timer value (secs)
\r
103 public void setKaTimer (short kaTimer) {
\r
104 _kaTimer = kaTimer;
\r
108 * Sets the accounting timer value
\r
109 * @param acctTimer Accounting timer value (secs)
\r
111 public void setAcctTimer (short acctTimer) {
\r
112 _acctTimer = acctTimer;
\r
116 * Gets the value of the keep-alive timer
\r
117 * @return Keep-alive timer value (secs)
\r
119 public short getKaTimer () {
\r
124 * Gets the accounting timer value
\r
125 * @return Accounting timer value (secs)
\r
127 public short getAcctTimer () {
\r
132 * Gets the connection map
\r
133 * @return A <tt>Hashtable</tt> holding the connection map
\r
135 public Hashtable getConnectionMap() {
\r
136 return new Hashtable(_connectionMap);
\r
140 * Gets the client-type
\r
141 * @return The client-type
\r
143 public short getClientType() {
\r
144 return _clientType;
\r
148 * Disconnects a PEP
\r
149 * @param pepID PEP-ID of the PEP to be disconnected
\r
150 * @param error COPS Error to be reported as a reason
\r
151 * @throws COPSException
\r
152 * @throws IOException
\r
154 public void disconnect (String pepID, COPSError error)
\r
155 throws COPSException, IOException {
\r
157 COPSPdpConnection pdpConn = _connectionMap.get(pepID);
\r
159 COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, _clientType);
\r
160 COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
\r
161 closeMsg.add(cHdr);
\r
163 closeMsg.add(error);
\r
165 closeMsg.writeData(pdpConn.getSocket());
\r
170 * Requests a COPS sync for a PEP
\r
171 * @param pepID PEP-ID of the PEP to be synced
\r
172 * @throws COPSException
\r
173 * @throws COPSPdpException
\r
175 public void sync (String pepID)
\r
176 throws COPSException, COPSPdpException {
\r
178 COPSPdpConnection pdpConn = _connectionMap.get(pepID);
\r
179 pdpConn.syncAllRequestState();
\r
183 * Removes a PEP from the connection map
\r
184 * @param pepID PEP-ID of the PEP to be removed
\r
186 public void delete (String pepID) {
\r
187 _connectionMap.remove(pepID);
\r
192 * Runs the PDP process
\r
194 public void run() {
\r
196 final ServerSocket serverSocket = new ServerSocket (_serverPort);
\r
198 //Loop through for Incoming messages
\r
200 // server infinite loop
\r
203 // Wait for an incoming connection from a PEP
\r
204 Socket socket = serverSocket.accept();
\r
206 // COPSDebug.out(getClass().getName(),"New connection accepted " +
\r
207 // socket.getInetAddress() +
\r
208 // ":" + socket.getPort());
\r
210 // We're waiting for an OPN message
\r
212 COPSMsg msg = COPSTransceiver.receiveMsg(socket);
\r
213 if (msg.getHeader().isAClientOpen()) {
\r
214 handleClientOpenMsg(socket, msg);
\r
216 // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
\r
219 } catch (Exception ex) {
\r
220 logger.error("Error closing socket", ex);
\r
223 } catch (Exception e) { // COPSException, IOException
\r
224 // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,
\r
225 // "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);
\r
228 } catch (Exception ex) {
\r
229 logger.error("Error closing socket", ex);
\r
233 } catch (IOException e) {
\r
234 logger.error("Error caught while processing socket messages", e);
\r
239 * Handles a COPS client-open message
\r
240 * @param conn Socket to the PEP
\r
241 * @param msg <tt>COPSMsg</tt> holding the client-open message
\r
242 * @throws COPSException
\r
243 * @throws IOException
\r
245 private void handleClientOpenMsg(Socket conn, COPSMsg msg)
\r
246 throws COPSException, IOException {
\r
247 COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
\r
248 COPSPepId pepId = cMsg.getPepId();
\r
250 // Validate Client Type
\r
251 if (msg.getHeader().getClientType() != _clientType) {
\r
252 // Unsupported client type
\r
253 COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());
\r
254 COPSError err = new COPSError(COPSError.COPS_ERR_UNSUPPORTED_CLIENT_TYPE, (short) 0);
\r
255 COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
\r
256 closeMsg.add(cHdr);
\r
259 closeMsg.writeData(conn);
\r
260 } catch (IOException unae) {
\r
261 logger.error("Error writing COPS data", unae);
\r
264 throw new COPSException("Unsupported client type");
\r
267 // PEPId is mandatory
\r
268 if (pepId == null) {
\r
269 // Mandatory COPS object missing
\r
270 COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());
\r
271 COPSError err = new COPSError(COPSError.COPS_ERR_MANDATORY_OBJECT_MISSING, (short) 0);
\r
272 COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
\r
273 closeMsg.add(cHdr);
\r
276 closeMsg.writeData(conn);
\r
277 } catch (IOException unae) {
\r
278 logger.error("Error writing close message", unae);
\r
281 throw new COPSException("Mandatory COPS object missing (PEPId)");
\r
285 if ( (cMsg.getClientSI() != null) ||
\r
286 (cMsg.getPdpAddress() != null) ||
\r
287 (cMsg.getIntegrity() != null)) {
\r
289 // Unsupported objects
\r
290 COPSHeader cHdr = new COPSHeader(COPSHeader.COPS_OP_CC, msg.getHeader().getClientType());
\r
291 COPSError err = new COPSError(COPSError.COPS_ERR_UNKNOWN_OBJECT, (short) 0);
\r
292 COPSClientCloseMsg closeMsg = new COPSClientCloseMsg();
\r
293 closeMsg.add(cHdr);
\r
296 closeMsg.writeData(conn);
\r
297 } catch (IOException unae) {
\r
298 logger.error("Error writing close message", unae);
\r
301 throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");
\r
304 // Connection accepted
\r
305 COPSHeader ahdr = new COPSHeader(COPSHeader.COPS_OP_CAT, msg.getHeader().getClientType());
\r
306 COPSKATimer katimer = new COPSKATimer(_kaTimer);
\r
307 COPSAcctTimer acctTimer = new COPSAcctTimer(_acctTimer);
\r
308 COPSClientAcceptMsg acceptMsg = new COPSClientAcceptMsg();
\r
309 acceptMsg.add(ahdr);
\r
310 acceptMsg.add(katimer) ;
\r
311 if (_acctTimer != 0) acceptMsg.add(acctTimer);
\r
312 acceptMsg.writeData(conn);
\r
314 COPSPdpConnection pdpConn = new COPSPdpConnection(pepId,conn,_process);
\r
315 pdpConn.setKaTimer(_kaTimer);
\r
316 if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);
\r
317 new Thread(pdpConn).start();
\r
318 _connectionMap.put(pepId.getData().str(),pdpConn);
\r