Expanded CMTS emulator to accept at least one type of gate request. Future work will...
[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.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;
18
19 import java.io.IOException;
20 import java.net.Socket;
21 import java.util.*;
22
23 /**
24  * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
25  * in PEP.
26  *
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.
41  *
42  * @version COPSPepReqStateMan.java, v 2.00 2004
43  *
44  */
45 public class COPSPepReqStateMan {
46
47     // TODO - place these values into an enumeration
48     /**
49      * Request State created
50      */
51     public final static short ST_CREATE = 1;
52     /**
53      * Request sent
54      */
55     public final static short ST_INIT = 2;
56     /**
57      * Decisions received
58      */
59     public final static short ST_DECS = 3;
60     /**
61      * Report sent
62      */
63     public final static short ST_REPORT = 4;
64     /**
65      * Request State finalized
66      */
67     public final static short ST_FINAL = 5;
68     /**
69      * New Request State solicited
70      */
71     public final static short ST_NEW = 6;
72     /**
73      * Delete Request State solicited
74      */
75     public final static short ST_DEL = 7;
76     /**
77      * SYNC Request received
78      */
79     public final static short ST_SYNC = 8;
80     /**
81      * SYNC Completed
82      */
83     public final static short ST_SYNCALL = 9;
84     /**
85      * Close Connection received
86      */
87     public final static short ST_CCONN = 10;
88     /**
89      * KAlive Time out
90      */
91     public final static short ST_NOKA = 11;
92     /**
93      * ACCT Time out
94      */
95     public final static short ST_ACCT = 12;
96
97     private final static Logger logger = LoggerFactory.getLogger(COPSPepReqStateMan.class);
98
99     /**
100      * The client-type identifies the policy client
101      */
102     protected short _clientType;
103
104     /**
105      *  The client handle is used to uniquely identify a particular
106      *  PEP's request for a client-type
107      */
108     protected COPSHandle _handle;
109
110     /**
111         The PolicyDataProcess is used to process policy data in the PEP
112      */
113     protected COPSPepDataProcess _process;
114
115     /**
116      *  State Request State
117      */
118     protected short _status;
119
120     /**
121         The Msg Sender is used to send COPS messages
122      */
123     protected COPSPepMsgSender _sender;
124
125     /**
126      * Sync State
127      */
128     protected boolean _syncState;
129
130     /**
131      * Create a State Request Manager
132      *
133      * @param    clientHandle                a Client Handle
134      *
135      */
136     public COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle) {
137         _handle = clientHandle;
138         _clientType = clientType;
139         _syncState = true;
140         _status = ST_CREATE;
141     }
142
143     /**
144      * Return client handle
145      *
146      * @return   a COPSHandle
147      *
148      */
149     public COPSHandle getClientHandle() {
150         return _handle;
151     }
152
153     /**
154      * Return client-type
155      *
156      * @return   a short
157      *
158      */
159     public int getClientType() {
160         return _clientType;
161     }
162
163     /**
164      * Return Request State status
165      *
166      * @return      s short
167      */
168     public short getStatus() {
169         return _status;
170     }
171
172     /**
173      * Return the Policy Data Process
174      *
175      * @return   a PolicyConfigure
176      *
177      */
178     public COPSPepDataProcess getDataProcess() {
179         return _process;
180     }
181
182     /**
183      * Establish the Policy Data Process
184      *
185      * @param    process              a  PolicyConfigure
186      *
187      */
188     public void setDataProcess(final COPSPepDataProcess process) {
189         _process = process;
190     }
191
192     /**
193      * Init Request State
194      *
195      * @throws   COPSPepException
196      *
197      */
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);
201
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);
207         else
208             clientSIs = new HashMap<>();
209
210         // Send the request
211         // TODO - do we really want to send when this is empty???
212         _sender.sendRequest(clientSIs);
213
214         // Initial state
215         _status = ST_INIT;
216     }
217
218     /**
219      * Finalize Request State
220      *
221      * @throws   COPSPepException
222      *
223      */
224     protected void finalizeRequestState() throws COPSPepException {
225         _sender.sendDeleteRequest();
226         _status = ST_FINAL;
227     }
228
229     /**
230      * Process the message Decision
231      *
232      * @param    dMsg                a  COPSDecisionMsg
233      *
234      * @throws   COPSPepException
235      *
236      */
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();
240
241         final Map<String, String> removeDecs = new HashMap<>();
242         final Map<String, String> installDecs = new HashMap<>();
243
244         for (final Set<COPSDecision> copsDecisions: decisions.values()) {
245             final COPSDecision cmddecision = copsDecisions.iterator().next();
246             String prid = "";
247             switch (cmddecision.getCommand()) {
248                 case INSTALL:
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();
256                                     break;
257                                 case COPSPrObjBase.PR_EPD:
258                                     installDecs.put(prid, obj.getData().str());
259                                     break;
260                             }
261                         }
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;
272
273                                 // Set response
274                                 final List<Byte> data = new ArrayList<>();
275                                 for (final byte val : gateReq.getTransactionID().getAsBinaryArray())
276                                     data.add(val);
277                                 for (final byte val : gateReq.getAMID().getAsBinaryArray())
278                                     data.add(val);
279                                 for (final byte val : gateReq.getSubscriberID().getAsBinaryArray())
280                                     data.add(val);
281
282                                 // Assign a gate ID
283                                 final GateID gateID = new GateID();
284                                 gateID.setGateID(UUID.randomUUID().hashCode());
285                                 for (final byte val : gateID.getAsBinaryArray())
286                                     data.add(val);
287
288
289                                 final byte[] csiArr = new byte[data.size()];
290                                 for (int i = 0; i < data.size(); i++) {
291                                     csiArr[i] = data.get(i);
292                                 }
293                                 final COPSClientSI si = new COPSClientSI(CNum.CSI, CType.DEF, new COPSData(csiArr, 0, csiArr.length));
294
295                                 final COPSReportMsg reportMsg;
296                                 if (success) {
297                                     reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
298                                             new COPSReportType(ReportType.SUCCESS), si, null);
299                                 } else {
300                                     reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
301                                             new COPSReportType(ReportType.FAILURE), si, null);
302                                 }
303
304                                 try {
305                                     reportMsg.writeData(socket);
306                                 } catch (IOException e) {
307                                     throw new COPSPepException("Error writing gate set SUCCESS Report", e);
308                                 }
309                             }
310                         }
311                     }
312                     break;
313                 case REMOVE:
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();
319                                 break;
320                             case COPSPrObjBase.PR_EPD:
321                                 removeDecs.put(prid, obj.getData().str());
322                                 break;
323                             default:
324                                 break;
325                         }
326                     }
327                     break;
328             }
329
330         }
331
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);
336         _status = ST_DECS;
337
338
339         if (_process.isFailReport(this)) {
340             // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
341             _sender.sendFailReport(_process.getReportData(this));
342         } else {
343             // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
344             _sender.sendSuccessReport(_process.getReportData(this));
345         }
346         _status = ST_REPORT;
347
348         if (!_syncState) {
349             _sender.sendSyncComplete();
350             _syncState = true;
351             _status = ST_SYNCALL;
352         }
353     }
354
355     /**
356      * Process the message NewRequestState
357      *
358      * @throws   COPSPepException
359      *
360      */
361     protected void processOpenNewRequestState() throws COPSPepException {
362
363         if (_process != null)
364             _process.newRequestState(this);
365
366         _status = ST_NEW;
367     }
368
369     /**
370      * Process the message DeleteRequestState
371      *
372      * @param    dMsg                a  COPSDecisionMsg
373      *
374      * @throws   COPSPepException
375      *
376      */
377     protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
378         if (_process != null)
379             _process.closeRequestState(this);
380
381         _status = ST_DEL;
382     }
383
384     /**
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.
389      *
390      * @param    ssMsg               a  COPSSyncStateMsg
391      *
392      * @throws   COPSPepException
393      *
394      */
395     protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSPepException {
396         _syncState = false;
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);
402         else
403             clientSIs = new HashMap<>();
404
405         // Send request
406         // TODO - do we really want to send the request when the map is empty???
407         _sender.sendRequest(clientSIs);
408
409         _status = ST_SYNC;
410     }
411
412     protected void processClosedConnection(final COPSError error) throws COPSPepException {
413         if (_process != null)
414             _process.notifyClosedConnection(this, error);
415
416         _status = ST_CCONN;
417     }
418
419     protected void processNoKAConnection() throws COPSPepException {
420         if (_process != null)
421             _process.notifyNoKAliveReceived(this);
422
423         _status = ST_NOKA;
424     }
425
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<>();
430
431         // TODO - do we really want to send when the map is empty???
432         _sender.sendAcctReport(report);
433
434         _status = ST_ACCT;
435     }
436
437 }