Merge changes Ic442b16e,Ibeb2c05b,Ibadb787a,I5fd9b5dd,Ia751f131, ...
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / prpep / COPSPepReqStateMan.java
1 /*
2  * Copyright (c) 2004 University of Murcia.  All rights reserved.
3  * --------------------------------------------------------------
4  * For more information, please see <http://www.umu.euro6ix.org/>.
5  */
6
7 package org.umu.cops.prpep;
8
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;
19
20 import java.io.IOException;
21 import java.net.Socket;
22 import java.util.*;
23
24 /**
25  * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
26  * in PEP.
27  *
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.
42  *
43  * @version COPSPepReqStateMan.java, v 2.00 2004
44  *
45  */
46 public class COPSPepReqStateMan extends COPSStateMan {
47
48     private final static Logger logger = LoggerFactory.getLogger(COPSPepReqStateMan.class);
49
50     /**
51         The PolicyDataProcess is used to process policy data in the PEP
52      */
53     protected final COPSPepDataProcess _process;
54
55     /**
56         The Msg Sender is used to send COPS messages
57      */
58     protected transient COPSPepMsgSender _sender;
59
60     /**
61      * Sync State
62      */
63     protected transient boolean _syncState;
64
65     /**
66      * Create a State Request Manager
67      *
68      * @param    clientHandle                a Client Handle
69      *
70      */
71     public COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPepDataProcess process) {
72         super(clientType, clientHandle);
73         this._process = process;
74         _syncState = true;
75     }
76
77     /**
78      * Init Request State
79      *
80      * @throws   COPSPepException
81      *
82      */
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);
86
87         // If an object for retrieving PEP features exists,
88         // use it for retrieving them
89         final Map<String, String> clientSIs;
90         if (_process != null)
91             clientSIs = _process.getClientData(this);
92         else
93             clientSIs = new HashMap<>();
94
95         // Send the request
96         // TODO - do we really want to send when this is empty???
97         _sender.sendRequest(clientSIs);
98
99         // Initial state
100         _status = Status.ST_INIT;
101     }
102
103     /**
104      * Finalize Request State
105      *
106      * @throws   COPSPepException
107      *
108      */
109     public void finalizeRequestState() throws COPSException {
110         _sender.sendDeleteRequest();
111         _status = Status.ST_FINAL;
112     }
113
114     /**
115      * Process the message Decision
116      *
117      * @param    dMsg                a  COPSDecisionMsg
118      *
119      * @throws   COPSPepException
120      *
121      */
122     protected void processDecision(final COPSDecisionMsg dMsg, final Socket socket) throws COPSException {
123         logger.info("Processing decision message - " + dMsg);
124         final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
125
126         final Map<String, String> removeDecs = new HashMap<>();
127         final Map<String, String> installDecs = new HashMap<>();
128
129         for (final Set<COPSDecision> copsDecisions: decisions.values()) {
130             final COPSDecision cmddecision = copsDecisions.iterator().next();
131             String prid = "";
132             switch (cmddecision.getCommand()) {
133                 case INSTALL:
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();
141                                     break;
142                                 case COPSPrObjBase.PR_EPD:
143                                     installDecs.put(prid, obj.getData().str());
144                                     break;
145                             }
146                         }
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;
157
158                                 // Set response
159                                 final List<Byte> data = new ArrayList<>();
160                                 for (final byte val : gateReq.getTransactionID().getAsBinaryArray())
161                                     data.add(val);
162                                 for (final byte val : gateReq.getAMID().getAsBinaryArray())
163                                     data.add(val);
164                                 for (final byte val : gateReq.getSubscriberID().getAsBinaryArray())
165                                     data.add(val);
166
167                                 // Assign a gate ID
168                                 final GateID gateID = new GateID();
169                                 gateID.setGateID(UUID.randomUUID().hashCode());
170                                 for (final byte val : gateID.getAsBinaryArray())
171                                     data.add(val);
172
173
174                                 final byte[] csiArr = new byte[data.size()];
175                                 for (int i = 0; i < data.size(); i++) {
176                                     csiArr[i] = data.get(i);
177                                 }
178                                 final COPSClientSI si = new COPSClientSI(CNum.CSI, CType.DEF, new COPSData(csiArr, 0, csiArr.length));
179
180                                 final COPSReportMsg reportMsg;
181                                 // TODO FIXME - success is always true
182                                 if (success) {
183                                     reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
184                                             new COPSReportType(ReportType.SUCCESS), si, null);
185                                 } else {
186                                     reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
187                                             new COPSReportType(ReportType.FAILURE), si, null);
188                                 }
189
190                                 try {
191                                     reportMsg.writeData(socket);
192                                 } catch (IOException e) {
193                                     throw new COPSPepException("Error writing gate set SUCCESS Report", e);
194                                 }
195                             }
196                         }
197                     }
198                     break;
199                 case REMOVE:
200                     for (final COPSDecision decision : copsDecisions) {
201                         final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
202                         switch (obj.getSNum()) {
203                             case COPSPrObjBase.PR_PRID:
204                                 prid = obj.getData().str();
205                                 break;
206                             case COPSPrObjBase.PR_EPD:
207                                 removeDecs.put(prid, obj.getData().str());
208                                 break;
209                             default:
210                                 break;
211                         }
212                     }
213                     break;
214             }
215
216         }
217
218         //** Apply decisions to the configuration
219         // TODO - why is this collection never getting populated???
220         final Map<String, String> errorDecs = new HashMap<>();
221         _process.setDecisions(this, removeDecs, installDecs, errorDecs);
222         _status = Status.ST_DECS;
223
224
225         if (_process.isFailReport(this)) {
226             // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
227             _sender.sendFailReport(_process.getReportData(this));
228         } else {
229             // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
230             _sender.sendSuccessReport(_process.getReportData(this));
231         }
232         _status = Status.ST_REPORT;
233
234         if (!_syncState) {
235             _sender.sendSyncComplete();
236             _syncState = true;
237             _status = Status.ST_SYNCALL;
238         }
239     }
240
241     /**
242      * Process the message NewRequestState
243      *
244      * @throws   COPSPepException
245      *
246      */
247     protected void processOpenNewRequestState() throws COPSPepException {
248
249         if (_process != null)
250             _process.newRequestState(this);
251
252         _status = Status.ST_NEW;
253     }
254
255     /**
256      * Process the message DeleteRequestState
257      *
258      * @param    dMsg                a  COPSDecisionMsg
259      *
260      * @throws   COPSPepException
261      *
262      */
263     protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
264         if (_process != null)
265             _process.closeRequestState(this);
266
267         _status = Status.ST_DEL;
268     }
269
270     /**
271      * Process the message SycnStateRequest.
272      * The message SycnStateRequest indicates that the remote PDP
273      * wishes the client (which appears in the common header)
274      * to re-send its state.
275      *
276      * @param    ssMsg               a  COPSSyncStateMsg
277      *
278      * @throws   COPSPepException
279      *
280      */
281     protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSException {
282         _syncState = false;
283         // If an object for retrieving PEP features exists,
284         // use it for retrieving them
285         final Map<String, String> clientSIs;
286         if (_process != null)
287             clientSIs = _process.getClientData(this);
288         else
289             clientSIs = new HashMap<>();
290
291         // Send request
292         // TODO - do we really want to send the request when the map is empty???
293         _sender.sendRequest(clientSIs);
294
295         _status = Status.ST_SYNC;
296     }
297
298     public void processClosedConnection(final COPSError error) throws COPSPepException {
299         if (_process != null)
300             _process.notifyClosedConnection(this, error);
301
302         _status = Status.ST_CCONN;
303     }
304
305     public void processNoKAConnection() throws COPSException {
306         if (_process != null)
307             _process.notifyNoKAliveReceived(this);
308
309         _status = Status.ST_NOKA;
310     }
311
312     public void processAcctReport() throws COPSException {
313         final Map<String, String> report;
314         if (_process != null) report = _process.getAcctData(this);
315         else report = new HashMap<>();
316
317         // TODO - do we really want to send when the map is empty???
318         _sender.sendAcctReport(report);
319
320         _status = Status.ST_ACCT;
321     }
322
323 }