1 package org.umu.cops.ospdp;
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.umu.cops.stack.*;
6 import org.umu.cops.stack.COPSError.ErrorTypes;
7 import org.umu.cops.stack.COPSHeader.ClientType;
8 import org.umu.cops.stack.COPSHeader.OPCode;
10 import java.io.IOException;
11 import java.net.ServerSocket;
12 import java.net.Socket;
14 import java.util.concurrent.ConcurrentHashMap;
17 * Core PDP agent for outsourcing.
19 public class COPSPdpOSAgent extends Thread {
21 public final static Logger logger = LoggerFactory.getLogger(COPSPdpOSAgent.class);
23 /** Well-known port for COPS */
24 public static final int WELL_KNOWN_PDP_PORT = 3288;
25 /** Default keep-alive timer value (secs) */
26 public static final short KA_TIMER_VALUE = 30;
27 /** Default accounting timer value (secs) */
28 public static final short ACCT_TIMER_VALUE = 0;
33 private int _serverPort;
36 Client-type of connecting PEP
38 private ClientType _clientType;
41 Accounting timer (secs)
43 private short _acctTimer;
46 Keep-alive timer (secs)
48 private short _kaTimer;
51 Maps a PEP-ID to a connection
53 private final Map<String, COPSPdpOSConnection> _connectionMap;
54 // map < String(PEPID), COPSPdpOSConnection > ConnectionMap;
57 * Policy data processing object
59 private COPSPdpOSDataProcess _process;
64 * @param clientType COPS Client-type
65 * @param process Object to perform policy data processing
67 public COPSPdpOSAgent(final ClientType clientType, final COPSPdpOSDataProcess process) {
68 _serverPort = WELL_KNOWN_PDP_PORT;
69 _kaTimer = KA_TIMER_VALUE;
70 _acctTimer = ACCT_TIMER_VALUE;
72 _clientType = clientType;
73 _connectionMap = new ConcurrentHashMap<>();
80 * @param port Port to listen to
81 * @param clientType COPS Client-type
82 * @param process Object to perform policy data processing
84 public COPSPdpOSAgent(final int port, final ClientType clientType, final COPSPdpOSDataProcess process) {
87 _kaTimer = KA_TIMER_VALUE;
88 _acctTimer = ACCT_TIMER_VALUE;
90 _clientType = clientType;
91 _connectionMap = new ConcurrentHashMap<>();
96 * Sets the keep-alive timer value
97 * @param kaTimer Keep alive timer value (secs)
99 public void setKaTimer (short kaTimer) {
104 * Sets the accounting timer value
105 * @param acctTimer Accounting timer value (secs)
107 public void setAcctTimer (short acctTimer) {
108 _acctTimer = acctTimer;
112 * Gets the value of the keep-alive timer
113 * @return Keep-alive timer value (secs)
115 public short getKaTimer () {
120 * Gets the accounting timer value
121 * @return Accounting timer value (secs)
123 public short getAcctTimer () {
128 * Gets the client-type
129 * @return The client-type
131 public ClientType getClientType() {
137 * @param pepID PEP-ID of the PEP to be disconnected
138 * @param error COPS Error to be reported as a reason
139 * @throws COPSException
140 * @throws IOException
142 public void disconnect(final String pepID, final COPSError error) throws COPSException, IOException {
143 final COPSPdpOSConnection pdpConn = _connectionMap.get(pepID);
144 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
145 closeMsg.writeData(pdpConn.getSocket());
150 * Requests a COPS sync for a PEP
151 * @param pepID PEP-ID of the PEP to be synced
152 * @throws COPSException
153 * @throws COPSPdpException
155 public void sync(String pepID) throws COPSException, COPSPdpException {
156 COPSPdpOSConnection pdpConn = _connectionMap.get(pepID);
157 pdpConn.syncAllRequestState();
161 * Removes a PEP from the connection map
162 * @param pepID PEP-ID of the PEP to be removed
164 public void delete (String pepID) {
165 _connectionMap.remove(pepID);
169 * Runs the PDP process
173 final ServerSocket serverSocket = new ServerSocket (_serverPort);
175 //Loop through for Incoming messages
177 // server infinite loop
179 // Wait for an incoming connection from a PEP
180 Socket socket = serverSocket.accept();
182 // COPSDebug.out(getClass().getName(),"New connection accepted " +
183 // socket.getInetAddress() +
184 // ":" + socket.getPort());
186 // We're waiting for an OPN message
188 COPSMsg msg = COPSTransceiver.receiveMsg(socket);
189 if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
190 handleClientOpenMsg(socket, msg);
192 // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
195 } catch (Exception ex) {
196 logger.error("Error closing socket", ex);
199 } catch (Exception e) { // COPSException, IOException
200 // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,
201 // "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);
204 } catch (Exception ex) {
205 logger.error("Error closing socket", ex);
209 } catch (IOException e) {
210 logger.error("Error processing socket messages", e);
215 * Handles a COPS client-open message
216 * @param conn Socket to the PEP
217 * @param msg <tt>COPSMsg</tt> holding the client-open message
218 * @throws COPSException
219 * @throws IOException
221 private void handleClientOpenMsg(Socket conn, COPSMsg msg) throws COPSException, IOException {
222 COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
223 COPSPepId pepId = cMsg.getPepId();
225 // Validate Client Type
226 if (msg.getHeader().getClientType() != _clientType) {
227 // Unsupported client type
228 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
229 new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
231 closeMsg.writeData(conn);
232 } catch (IOException unae) {
233 logger.error("Error writing data", unae);
236 throw new COPSException("Unsupported client type");
239 // PEPId is mandatory
241 // Mandatory COPS object missing
242 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
243 new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
245 closeMsg.writeData(conn);
246 } catch (IOException unae) {
247 logger.error("Error writing data", unae);
250 throw new COPSException("Mandatory COPS object missing (PEPId)");
254 if ( (cMsg.getClientSI() != null) || (cMsg.getPdpAddress() != null) || (cMsg.getIntegrity() != null)) {
256 // Unsupported objects
257 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
258 new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
260 closeMsg.writeData(conn);
261 } catch (IOException unae) {
262 logger.error("Error writing data", unae);
265 throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");
268 // Connection accepted
269 final COPSKATimer katimer = new COPSKATimer(_kaTimer);
270 final COPSClientAcceptMsg acceptMsg;
272 acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, new COPSAcctTimer(_acctTimer),
275 acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, null, null);
277 acceptMsg.writeData(conn);
279 final COPSPdpOSConnection pdpConn = new COPSPdpOSConnection(pepId, conn, _process);
280 pdpConn.setKaTimer(_kaTimer);
281 if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);
282 new Thread(pdpConn).start();
283 _connectionMap.put(pepId.getData().str(),pdpConn);