2 * Copyright (c) 2004 University of Murcia. All rights reserved.
3 * --------------------------------------------------------------
4 * For more information, please see <http://www.umu.euro6ix.org/>.
7 package org.umu.cops.prpep;
9 import org.pcmm.gates.impl.GateID;
10 import org.pcmm.gates.impl.PCMMGateReq;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13 import org.umu.cops.stack.*;
14 import org.umu.cops.stack.COPSDecision.DecisionFlag;
15 import org.umu.cops.stack.COPSObjHeader.CNum;
16 import org.umu.cops.stack.COPSObjHeader.CType;
17 import org.umu.cops.stack.COPSReportType.ReportType;
19 import java.io.IOException;
20 import java.net.Socket;
24 * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
27 * The client handle is used to identify a unique request state for a
28 * single PEP per client-type. Client handles are chosen by the PEP and
29 * are opaque to the PDP. The PDP simply uses the request handle to
30 * uniquely identify the request state for a particular Client-Type over
31 * a particular TCP connection and generically tie its decisions to a
32 * corresponding request. Client handles are initiated in request
33 * messages and are then used by subsequent request, decision, and
34 * report messages to reference the same request state. When the PEP is
35 * ready to remove a local request state, it will issue a delete message
36 * to the PDP for the corresponding client handle. A handle MUST be
37 * explicitly deleted by the PEP before it can be used by the PEP to
38 * identify a new request state. Handles referring to different request
39 * states MUST be unique within the context of a particular TCP
40 * connection and client-type.
42 * @version COPSPepReqStateMan.java, v 2.00 2004
45 public class COPSPepReqStateMan {
47 // TODO - place these values into an enumeration
49 * Request State created
51 public final static short ST_CREATE = 1;
55 public final static short ST_INIT = 2;
59 public final static short ST_DECS = 3;
63 public final static short ST_REPORT = 4;
65 * Request State finalized
67 public final static short ST_FINAL = 5;
69 * New Request State solicited
71 public final static short ST_NEW = 6;
73 * Delete Request State solicited
75 public final static short ST_DEL = 7;
77 * SYNC Request received
79 public final static short ST_SYNC = 8;
83 public final static short ST_SYNCALL = 9;
85 * Close Connection received
87 public final static short ST_CCONN = 10;
91 public final static short ST_NOKA = 11;
95 public final static short ST_ACCT = 12;
97 private final static Logger logger = LoggerFactory.getLogger(COPSPepReqStateMan.class);
100 * The client-type identifies the policy client
102 protected short _clientType;
105 * The client handle is used to uniquely identify a particular
106 * PEP's request for a client-type
108 protected COPSHandle _handle;
111 The PolicyDataProcess is used to process policy data in the PEP
113 protected COPSPepDataProcess _process;
116 * State Request State
118 protected short _status;
121 The Msg Sender is used to send COPS messages
123 protected COPSPepMsgSender _sender;
128 protected boolean _syncState;
131 * Create a State Request Manager
133 * @param clientHandle a Client Handle
136 public COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle) {
137 _handle = clientHandle;
138 _clientType = clientType;
144 * Return client handle
146 * @return a COPSHandle
149 public COPSHandle getClientHandle() {
159 public int getClientType() {
164 * Return Request State status
168 public short getStatus() {
173 * Return the Policy Data Process
175 * @return a PolicyConfigure
178 public COPSPepDataProcess getDataProcess() {
183 * Establish the Policy Data Process
185 * @param process a PolicyConfigure
188 public void setDataProcess(final COPSPepDataProcess process) {
195 * @throws COPSPepException
198 protected void initRequestState(final Socket sock) throws COPSPepException {
199 // Inits an object for sending COPS messages to the PDP
200 _sender = new COPSPepMsgSender(_clientType, _handle, sock);
202 // If an object for retrieving PEP features exists,
203 // use it for retrieving them
204 final Map<String, String> clientSIs;
205 if (_process != null)
206 clientSIs = _process.getClientData(this);
208 clientSIs = new HashMap<>();
211 // TODO - do we really want to send when this is empty???
212 _sender.sendRequest(clientSIs);
219 * Finalize Request State
221 * @throws COPSPepException
224 protected void finalizeRequestState() throws COPSPepException {
225 _sender.sendDeleteRequest();
230 * Process the message Decision
232 * @param dMsg a COPSDecisionMsg
234 * @throws COPSPepException
237 protected void processDecision(final COPSDecisionMsg dMsg, final Socket socket) throws COPSPepException {
238 logger.info("Processing decision message - " + dMsg);
239 final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
241 final Map<String, String> removeDecs = new HashMap<>();
242 final Map<String, String> installDecs = new HashMap<>();
244 for (final Set<COPSDecision> copsDecisions: decisions.values()) {
245 final COPSDecision cmddecision = copsDecisions.iterator().next();
247 switch (cmddecision.getCommand()) {
249 // TODO - break up this block
250 for (final COPSDecision decision : copsDecisions) {
251 if (decision.getData().getData().length != 0) {
252 final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
253 switch (obj.getSNum()) {
254 case COPSPrObjBase.PR_PRID:
255 prid = obj.getData().str();
257 case COPSPrObjBase.PR_EPD:
258 installDecs.put(prid, obj.getData().str());
262 if (decision.getFlag().equals(DecisionFlag.REQERROR)) {
263 // This is assuming a gate set right or wrong
264 if (dMsg.getDecisions().size() == 1 && dMsg.getDecSI() != null) {
265 final PCMMGateReq gateReq = new PCMMGateReq(dMsg.getDecSI().getData().getData());
266 // TODO - Check and/or Set state here
267 // Gate ADD gateReq.getTrafficProfile() != null
268 // Gate REMOVE gateReq.getTrafficProfile() == null
269 // final String gateName = trafficProfile.getData().str();
270 // final Direction gateDir = gateReq.getGateSpec().getDirection();
271 final boolean success = true;
274 final List<Byte> data = new ArrayList<>();
275 for (final byte val : gateReq.getTransactionID().getAsBinaryArray())
277 for (final byte val : gateReq.getAMID().getAsBinaryArray())
279 for (final byte val : gateReq.getSubscriberID().getAsBinaryArray())
283 final GateID gateID = new GateID();
284 gateID.setGateID(UUID.randomUUID().hashCode());
285 for (final byte val : gateID.getAsBinaryArray())
289 final byte[] csiArr = new byte[data.size()];
290 for (int i = 0; i < data.size(); i++) {
291 csiArr[i] = data.get(i);
293 final COPSClientSI si = new COPSClientSI(CNum.CSI, CType.DEF, new COPSData(csiArr, 0, csiArr.length));
295 final COPSReportMsg reportMsg;
297 reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
298 new COPSReportType(ReportType.SUCCESS), si, null);
300 reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
301 new COPSReportType(ReportType.FAILURE), si, null);
305 reportMsg.writeData(socket);
306 } catch (IOException e) {
307 throw new COPSPepException("Error writing gate set SUCCESS Report", e);
314 for (final COPSDecision decision : copsDecisions) {
315 final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
316 switch (obj.getSNum()) {
317 case COPSPrObjBase.PR_PRID:
318 prid = obj.getData().str();
320 case COPSPrObjBase.PR_EPD:
321 removeDecs.put(prid, obj.getData().str());
332 //** Apply decisions to the configuration
333 // TODO - why is this collection never getting populated???
334 final Map<String, String> errorDecs = new HashMap<>();
335 _process.setDecisions(this, removeDecs, installDecs, errorDecs);
339 if (_process.isFailReport(this)) {
340 // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
341 _sender.sendFailReport(_process.getReportData(this));
343 // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
344 _sender.sendSuccessReport(_process.getReportData(this));
349 _sender.sendSyncComplete();
351 _status = ST_SYNCALL;
356 * Process the message NewRequestState
358 * @throws COPSPepException
361 protected void processOpenNewRequestState() throws COPSPepException {
363 if (_process != null)
364 _process.newRequestState(this);
370 * Process the message DeleteRequestState
372 * @param dMsg a COPSDecisionMsg
374 * @throws COPSPepException
377 protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
378 if (_process != null)
379 _process.closeRequestState(this);
385 * Process the message SycnStateRequest.
386 * The message SycnStateRequest indicates that the remote PDP
387 * wishes the client (which appears in the common header)
388 * to re-send its state.
390 * @param ssMsg a COPSSyncStateMsg
392 * @throws COPSPepException
395 protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSPepException {
397 // If an object for retrieving PEP features exists,
398 // use it for retrieving them
399 final Map<String, String> clientSIs;
400 if (_process != null)
401 clientSIs = _process.getClientData(this);
403 clientSIs = new HashMap<>();
406 // TODO - do we really want to send the request when the map is empty???
407 _sender.sendRequest(clientSIs);
412 protected void processClosedConnection(final COPSError error) throws COPSPepException {
413 if (_process != null)
414 _process.notifyClosedConnection(this, error);
419 protected void processNoKAConnection() throws COPSPepException {
420 if (_process != null)
421 _process.notifyNoKAliveReceived(this);
426 protected void processAcctReport() throws COPSPepException {
427 final Map<String, String> report;
428 if (_process != null) report = _process.getAcctData(this);
429 else report = new HashMap<>();
431 // TODO - do we really want to send when the map is empty???
432 _sender.sendAcctReport(report);