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.COPSStateMan;
14 import org.umu.cops.stack.*;
15 import org.umu.cops.stack.COPSDecision.DecisionFlag;
16 import org.umu.cops.stack.COPSObjHeader.CNum;
17 import org.umu.cops.stack.COPSObjHeader.CType;
18 import org.umu.cops.stack.COPSReportType.ReportType;
20 import java.io.IOException;
21 import java.net.Socket;
25 * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
28 * The client handle is used to identify a unique request state for a
29 * single PEP per client-type. Client handles are chosen by the PEP and
30 * are opaque to the PDP. The PDP simply uses the request handle to
31 * uniquely identify the request state for a particular Client-Type over
32 * a particular TCP connection and generically tie its decisions to a
33 * corresponding request. Client handles are initiated in request
34 * messages and are then used by subsequent request, decision, and
35 * report messages to reference the same request state. When the PEP is
36 * ready to remove a local request state, it will issue a delete message
37 * to the PDP for the corresponding client handle. A handle MUST be
38 * explicitly deleted by the PEP before it can be used by the PEP to
39 * identify a new request state. Handles referring to different request
40 * states MUST be unique within the context of a particular TCP
41 * connection and client-type.
43 * @version COPSPepReqStateMan.java, v 2.00 2004
46 public class COPSPepReqStateMan extends COPSStateMan {
48 private final static Logger logger = LoggerFactory.getLogger(COPSPepReqStateMan.class);
51 The PolicyDataProcess is used to process policy data in the PEP
53 protected final COPSPepDataProcess _process;
56 The Msg Sender is used to send COPS messages
58 protected transient COPSPepMsgSender _sender;
63 protected transient boolean _syncState;
66 * Create a State Request Manager
68 * @param clientHandle a Client Handle
71 public COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPepDataProcess process) {
72 super(clientType, clientHandle);
73 this._process = process;
80 * @throws COPSPepException
83 protected void initRequestState(final Socket sock) throws COPSException {
84 // Inits an object for sending COPS messages to the PDP
85 _sender = new COPSPepMsgSender(_clientType, _handle, sock);
87 // If an object for retrieving PEP features exists,
88 // use it for retrieving them
89 final Map<String, String> clientSIs;
91 clientSIs = _process.getClientData(this);
93 clientSIs = new HashMap<>();
96 // TODO - do we really want to send when this is empty???
97 _sender.sendRequest(clientSIs);
100 _status = Status.ST_INIT;
104 * Finalize Request State
106 * @throws COPSPepException
109 protected void finalizeRequestState() throws COPSPepException {
110 _sender.sendDeleteRequest();
111 _status = Status.ST_FINAL;
115 * Process the message Decision
117 * @param dMsg a COPSDecisionMsg
119 * @throws COPSPepException
122 protected void processDecision(final COPSDecisionMsg dMsg, final Socket socket) throws COPSPepException {
123 logger.info("Processing decision message - " + dMsg);
124 final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
126 final Map<String, String> removeDecs = new HashMap<>();
127 final Map<String, String> installDecs = new HashMap<>();
129 for (final Set<COPSDecision> copsDecisions: decisions.values()) {
130 final COPSDecision cmddecision = copsDecisions.iterator().next();
132 switch (cmddecision.getCommand()) {
134 // TODO - break up this block
135 for (final COPSDecision decision : copsDecisions) {
136 if (decision.getData().getData().length != 0) {
137 final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
138 switch (obj.getSNum()) {
139 case COPSPrObjBase.PR_PRID:
140 prid = obj.getData().str();
142 case COPSPrObjBase.PR_EPD:
143 installDecs.put(prid, obj.getData().str());
147 if (decision.getFlag().equals(DecisionFlag.REQERROR)) {
148 // This is assuming a gate set right or wrong
149 if (dMsg.getDecisions().size() == 1 && dMsg.getDecSI() != null) {
150 final PCMMGateReq gateReq = new PCMMGateReq(dMsg.getDecSI().getData().getData());
151 // TODO - Check and/or Set state here
152 // Gate ADD gateReq.getTrafficProfile() != null
153 // Gate REMOVE gateReq.getTrafficProfile() == null
154 // final String gateName = trafficProfile.getData().str();
155 // final Direction gateDir = gateReq.getGateSpec().getDirection();
156 final boolean success = true;
159 final List<Byte> data = new ArrayList<>();
160 for (final byte val : gateReq.getTransactionID().getAsBinaryArray())
162 for (final byte val : gateReq.getAMID().getAsBinaryArray())
164 for (final byte val : gateReq.getSubscriberID().getAsBinaryArray())
168 final GateID gateID = new GateID();
169 gateID.setGateID(UUID.randomUUID().hashCode());
170 for (final byte val : gateID.getAsBinaryArray())
174 final byte[] csiArr = new byte[data.size()];
175 for (int i = 0; i < data.size(); i++) {
176 csiArr[i] = data.get(i);
178 final COPSClientSI si = new COPSClientSI(CNum.CSI, CType.DEF, new COPSData(csiArr, 0, csiArr.length));
180 final COPSReportMsg reportMsg;
182 reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
183 new COPSReportType(ReportType.SUCCESS), si, null);
185 reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
186 new COPSReportType(ReportType.FAILURE), si, null);
190 reportMsg.writeData(socket);
191 } catch (IOException e) {
192 throw new COPSPepException("Error writing gate set SUCCESS Report", e);
199 for (final COPSDecision decision : copsDecisions) {
200 final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
201 switch (obj.getSNum()) {
202 case COPSPrObjBase.PR_PRID:
203 prid = obj.getData().str();
205 case COPSPrObjBase.PR_EPD:
206 removeDecs.put(prid, obj.getData().str());
217 //** Apply decisions to the configuration
218 // TODO - why is this collection never getting populated???
219 final Map<String, String> errorDecs = new HashMap<>();
220 _process.setDecisions(this, removeDecs, installDecs, errorDecs);
221 _status = Status.ST_DECS;
224 if (_process.isFailReport(this)) {
225 // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
226 _sender.sendFailReport(_process.getReportData(this));
228 // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
229 _sender.sendSuccessReport(_process.getReportData(this));
231 _status = Status.ST_REPORT;
234 _sender.sendSyncComplete();
236 _status = Status.ST_SYNCALL;
241 * Process the message NewRequestState
243 * @throws COPSPepException
246 protected void processOpenNewRequestState() throws COPSPepException {
248 if (_process != null)
249 _process.newRequestState(this);
251 _status = Status.ST_NEW;
255 * Process the message DeleteRequestState
257 * @param dMsg a COPSDecisionMsg
259 * @throws COPSPepException
262 protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
263 if (_process != null)
264 _process.closeRequestState(this);
266 _status = Status.ST_DEL;
270 * Process the message SycnStateRequest.
271 * The message SycnStateRequest indicates that the remote PDP
272 * wishes the client (which appears in the common header)
273 * to re-send its state.
275 * @param ssMsg a COPSSyncStateMsg
277 * @throws COPSPepException
280 protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSPepException {
282 // If an object for retrieving PEP features exists,
283 // use it for retrieving them
284 final Map<String, String> clientSIs;
285 if (_process != null)
286 clientSIs = _process.getClientData(this);
288 clientSIs = new HashMap<>();
291 // TODO - do we really want to send the request when the map is empty???
292 _sender.sendRequest(clientSIs);
294 _status = Status.ST_SYNC;
297 protected void processClosedConnection(final COPSError error) throws COPSPepException {
298 if (_process != null)
299 _process.notifyClosedConnection(this, error);
301 _status = Status.ST_CCONN;
304 protected void processNoKAConnection() throws COPSPepException {
305 if (_process != null)
306 _process.notifyNoKAliveReceived(this);
308 _status = Status.ST_NOKA;
311 protected void processAcctReport() throws COPSPepException {
312 final Map<String, String> report;
313 if (_process != null) report = _process.getAcctData(this);
314 else report = new HashMap<>();
316 // TODO - do we really want to send when the map is empty???
317 _sender.sendAcctReport(report);
319 _status = Status.ST_ACCT;