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.OPCode;
9 import java.io.IOException;
10 import java.net.ServerSocket;
11 import java.net.Socket;
13 import java.util.concurrent.ConcurrentHashMap;
16 * Core PDP agent for outsourcing.
18 public class COPSPdpOSAgent extends Thread {
20 public final static Logger logger = LoggerFactory.getLogger(COPSPdpOSAgent.class);
22 /** Well-known port for COPS */
23 public static final int WELL_KNOWN_PDP_PORT = 3288;
24 /** Default keep-alive timer value (secs) */
25 public static final short KA_TIMER_VALUE = 30;
26 /** Default accounting timer value (secs) */
27 public static final short ACCT_TIMER_VALUE = 0;
32 private int _serverPort;
35 Client-type of connecting PEP
37 private short _clientType;
40 Accounting timer (secs)
42 private short _acctTimer;
45 Keep-alive timer (secs)
47 private short _kaTimer;
50 Maps a PEP-ID to a connection
52 private final Map<String, COPSPdpOSConnection> _connectionMap;
53 // map < String(PEPID), COPSPdpOSConnection > ConnectionMap;
56 * Policy data processing object
58 private COPSPdpOSDataProcess _process;
63 * @param clientType COPS Client-type
64 * @param process Object to perform policy data processing
66 public COPSPdpOSAgent(final short clientType, final COPSPdpOSDataProcess process) {
67 _serverPort = WELL_KNOWN_PDP_PORT;
68 _kaTimer = KA_TIMER_VALUE;
69 _acctTimer = ACCT_TIMER_VALUE;
71 _clientType = clientType;
72 _connectionMap = new ConcurrentHashMap<>();
79 * @param port Port to listen to
80 * @param clientType COPS Client-type
81 * @param process Object to perform policy data processing
83 public COPSPdpOSAgent(final int port, final short clientType, final COPSPdpOSDataProcess process) {
86 _kaTimer = KA_TIMER_VALUE;
87 _acctTimer = ACCT_TIMER_VALUE;
89 _clientType = clientType;
90 _connectionMap = new ConcurrentHashMap<>();
95 * Sets the keep-alive timer value
96 * @param kaTimer Keep alive timer value (secs)
98 public void setKaTimer (short kaTimer) {
103 * Sets the accounting timer value
104 * @param acctTimer Accounting timer value (secs)
106 public void setAcctTimer (short acctTimer) {
107 _acctTimer = acctTimer;
111 * Gets the value of the keep-alive timer
112 * @return Keep-alive timer value (secs)
114 public short getKaTimer () {
119 * Gets the accounting timer value
120 * @return Accounting timer value (secs)
122 public short getAcctTimer () {
127 * Gets the client-type
128 * @return The client-type
130 public int getClientType() {
136 * @param pepID PEP-ID of the PEP to be disconnected
137 * @param error COPS Error to be reported as a reason
138 * @throws COPSException
139 * @throws IOException
141 public void disconnect(final String pepID, final COPSError error) throws COPSException, IOException {
142 final COPSPdpOSConnection pdpConn = _connectionMap.get(pepID);
143 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
144 closeMsg.writeData(pdpConn.getSocket());
149 * Requests a COPS sync for a PEP
150 * @param pepID PEP-ID of the PEP to be synced
151 * @throws COPSException
152 * @throws COPSPdpException
154 public void sync(String pepID) throws COPSException, COPSPdpException {
155 COPSPdpOSConnection pdpConn = _connectionMap.get(pepID);
156 pdpConn.syncAllRequestState();
160 * Removes a PEP from the connection map
161 * @param pepID PEP-ID of the PEP to be removed
163 public void delete (String pepID) {
164 _connectionMap.remove(pepID);
168 * Runs the PDP process
172 final ServerSocket serverSocket = new ServerSocket (_serverPort);
174 //Loop through for Incoming messages
176 // server infinite loop
178 // Wait for an incoming connection from a PEP
179 Socket socket = serverSocket.accept();
181 // COPSDebug.out(getClass().getName(),"New connection accepted " +
182 // socket.getInetAddress() +
183 // ":" + socket.getPort());
185 // We're waiting for an OPN message
187 COPSMsg msg = COPSTransceiver.receiveMsg(socket);
188 if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
189 handleClientOpenMsg(socket, msg);
191 // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
194 } catch (Exception ex) {
195 logger.error("Error closing socket", ex);
198 } catch (Exception e) { // COPSException, IOException
199 // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_EXCEPTION,
200 // "(" + socket.getInetAddress() + ":" + socket.getPort() + ")", e);
203 } catch (Exception ex) {
204 logger.error("Error closing socket", ex);
208 } catch (IOException e) {
209 logger.error("Error processing socket messages", e);
214 * Handles a COPS client-open message
215 * @param conn Socket to the PEP
216 * @param msg <tt>COPSMsg</tt> holding the client-open message
217 * @throws COPSException
218 * @throws IOException
220 private void handleClientOpenMsg(Socket conn, COPSMsg msg) throws COPSException, IOException {
221 COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
222 COPSPepId pepId = cMsg.getPepId();
224 // Validate Client Type
225 if (msg.getHeader().getClientType() != _clientType) {
226 // Unsupported client type
227 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
228 new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
230 closeMsg.writeData(conn);
231 } catch (IOException unae) {
232 logger.error("Error writing data", unae);
235 throw new COPSException("Unsupported client type");
238 // PEPId is mandatory
240 // Mandatory COPS object missing
241 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
242 new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
244 closeMsg.writeData(conn);
245 } catch (IOException unae) {
246 logger.error("Error writing data", unae);
249 throw new COPSException("Mandatory COPS object missing (PEPId)");
253 if ( (cMsg.getClientSI() != null) || (cMsg.getPdpAddress() != null) || (cMsg.getIntegrity() != null)) {
255 // Unsupported objects
256 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
257 new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
259 closeMsg.writeData(conn);
260 } catch (IOException unae) {
261 logger.error("Error writing data", unae);
264 throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");
267 // Connection accepted
268 final COPSKATimer katimer = new COPSKATimer(_kaTimer);
269 final COPSClientAcceptMsg acceptMsg;
271 acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, new COPSAcctTimer(_acctTimer),
274 acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, null, null);
276 acceptMsg.writeData(conn);
278 final COPSPdpOSConnection pdpConn = new COPSPdpOSConnection(pepId, conn, _process);
279 pdpConn.setKaTimer(_kaTimer);
280 if (_acctTimer != 0) pdpConn.setAcctTimer(_acctTimer);
281 new Thread(pdpConn).start();
282 _connectionMap.put(pepId.getData().str(),pdpConn);