Merge "Completed COPS Message refactoring. Was planning on one additional patch start...
[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.umu.cops.stack.*;
10 import org.umu.cops.stack.COPSHeader.ClientType;
11
12 import java.net.Socket;
13 import java.util.HashMap;
14 import java.util.Map;
15 import java.util.Set;
16
17 /**
18  * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
19  * in PEP.
20  *
21  *   The client handle is used to identify a unique request state for a
22  *   single PEP per client-type. Client handles are chosen by the PEP and
23  *   are opaque to the PDP. The PDP simply uses the request handle to
24  *   uniquely identify the request state for a particular Client-Type over
25  *   a particular TCP connection and generically tie its decisions to a
26  *   corresponding request. Client handles are initiated in request
27  *   messages and are then used by subsequent request, decision, and
28  *   report messages to reference the same request state. When the PEP is
29  *   ready to remove a local request state, it will issue a delete message
30  *   to the PDP for the corresponding client handle. A handle MUST be
31  *   explicitly deleted by the PEP before it can be used by the PEP to
32  *   identify a new request state. Handles referring to different request
33  *   states MUST be unique within the context of a particular TCP
34  *   connection and client-type.
35  *
36  * @version COPSPepReqStateMan.java, v 2.00 2004
37  *
38  */
39 public class COPSPepReqStateMan {
40
41     /**
42      * Request State created
43      */
44     public final static short ST_CREATE = 1;
45     /**
46      * Request sent
47      */
48     public final static short ST_INIT = 2;
49     /**
50      * Decisions received
51      */
52     public final static short ST_DECS = 3;
53     /**
54      * Report sent
55      */
56     public final static short ST_REPORT = 4;
57     /**
58      * Request State finalized
59      */
60     public final static short ST_FINAL = 5;
61     /**
62      * New Request State solicited
63      */
64     public final static short ST_NEW = 6;
65     /**
66      * Delete Request State solicited
67      */
68     public final static short ST_DEL = 7;
69     /**
70      * SYNC Request received
71      */
72     public final static short ST_SYNC = 8;
73     /**
74      * SYNC Completed
75      */
76     public final static short ST_SYNCALL = 9;
77     /**
78      * Close Connection received
79      */
80     public final static short ST_CCONN = 10;
81     /**
82      * KAlive Time out
83      */
84     public final static short ST_NOKA = 11;
85     /**
86      * ACCT Time out
87      */
88     public final static short ST_ACCT = 12;
89
90     /**
91      * The client-type identifies the policy client
92      */
93     protected ClientType _clientType;
94
95     /**
96      *  The client handle is used to uniquely identify a particular
97      *  PEP's request for a client-type
98      */
99     protected COPSHandle _handle;
100
101     /**
102         The PolicyDataProcess is used to process policy data in the PEP
103      */
104     protected COPSPepDataProcess _process;
105
106     /**
107      *  State Request State
108      */
109     protected short _status;
110
111     /**
112         The Msg Sender is used to send COPS messages
113      */
114     protected COPSPepMsgSender _sender;
115
116     /**
117      * Sync State
118      */
119     protected boolean _syncState;
120
121     /**
122      * Create a State Request Manager
123      *
124      * @param    clientHandle                a Client Handle
125      *
126      */
127     public COPSPepReqStateMan(final ClientType clientType, final String clientHandle) {
128         _handle = new COPSHandle(new COPSData(clientHandle));
129         _clientType = clientType;
130         _syncState = true;
131         _status = ST_CREATE;
132     }
133
134     /**
135      * Return client handle
136      *
137      * @return   a COPSHandle
138      *
139      */
140     public COPSHandle getClientHandle() {
141         return _handle;
142     }
143
144     /**
145      * Return client-type
146      *
147      * @return   a short
148      *
149      */
150     public ClientType getClientType() {
151         return _clientType;
152     }
153
154     /**
155      * Return Request State status
156      *
157      * @return      s short
158      */
159     public short getStatus() {
160         return _status;
161     }
162
163     /**
164      * Return the Policy Data Process
165      *
166      * @return   a PolicyConfigure
167      *
168      */
169     public COPSPepDataProcess getDataProcess() {
170         return _process;
171     }
172
173     /**
174      * Establish the Policy Data Process
175      *
176      * @param    process              a  PolicyConfigure
177      *
178      */
179     public void setDataProcess(COPSPepDataProcess process) {
180         _process = process;
181     }
182
183     /**
184      * Init Request State
185      *
186      * @throws   COPSPepException
187      *
188      */
189     protected void initRequestState(Socket sock)
190     throws COPSPepException {
191         // Inits an object for sending COPS messages to the PDP
192         _sender = new COPSPepMsgSender(_clientType, _handle, sock);
193
194         // If an object for retrieving PEP features exists,
195         // use it for retrieving them
196         final Map<String, String> clientSIs;
197         if (_process != null)
198             clientSIs = _process.getClientData(this);
199         else
200             clientSIs = new HashMap<>();
201
202         // Send the request
203         // TODO - do we really want to send when this is empty???
204         _sender.sendRequest(clientSIs);
205
206         // Initial state
207         _status = ST_INIT;
208     }
209
210     /**
211      * Finalize Request State
212      *
213      * @throws   COPSPepException
214      *
215      */
216     protected void finalizeRequestState()
217     throws COPSPepException {
218         _sender.sendDeleteRequest();
219         _status = ST_FINAL;
220     }
221
222     /**
223      * Process the message Decision
224      *
225      * @param    dMsg                a  COPSDecisionMsg
226      *
227      * @throws   COPSPepException
228      *
229      */
230     protected void processDecision(COPSDecisionMsg dMsg)
231     throws COPSPepException {
232         // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());
233
234         // COPSHandle handle = dMsg.getClientHandle();
235         final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
236
237         final Map<String, String> removeDecs = new HashMap<>();
238         final Map<String, String> installDecs = new HashMap<>();
239
240         for (Set<COPSDecision> copsDecisions: decisions.values()) {
241             final COPSDecision cmddecision = copsDecisions.iterator().next();
242             String prid = "";
243             switch (cmddecision.getCommand()) {
244                 case INSTALL:
245                     for (final COPSDecision decision : copsDecisions) {
246                         final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
247                         switch (obj.getSNum()) {
248                             case COPSPrObjBase.PR_PRID:
249                                 prid = obj.getData().str();
250                                 break;
251                             case COPSPrObjBase.PR_EPD:
252                                 installDecs.put(prid, obj.getData().str());
253                                 break;
254                             default:
255                                 break;
256                         }
257                     }
258                     break;
259                 case REMOVE:
260                     for (final COPSDecision decision : copsDecisions) {
261                         final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
262                         switch (obj.getSNum()) {
263                             case COPSPrObjBase.PR_PRID:
264                                 prid = obj.getData().str();
265                                 break;
266                             case COPSPrObjBase.PR_EPD:
267                                 removeDecs.put(prid, obj.getData().str());
268                                 break;
269                             default:
270                                 break;
271                         }
272                     }
273                     break;
274             }
275
276         }
277
278         //** Apply decisions to the configuration
279         // TODO - why is this collection never getting populated???
280         final Map<String, String> errorDecs = new HashMap<>();
281         _process.setDecisions(this, removeDecs, installDecs, errorDecs);
282         _status = ST_DECS;
283
284
285         if (_process.isFailReport(this)) {
286             // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
287             _sender.sendFailReport(_process.getReportData(this));
288         } else {
289             // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
290             _sender.sendSuccessReport(_process.getReportData(this));
291         }
292         _status = ST_REPORT;
293
294         if (!_syncState) {
295             _sender.sendSyncComplete();
296             _syncState = true;
297             _status = ST_SYNCALL;
298         }
299     }
300
301     /**
302      * Process the message NewRequestState
303      *
304      * @throws   COPSPepException
305      *
306      */
307     protected void processOpenNewRequestState()
308     throws COPSPepException {
309
310         if (_process != null)
311             _process.newRequestState(this);
312
313         _status = ST_NEW;
314     }
315
316     /**
317      * Process the message DeleteRequestState
318      *
319      * @param    dMsg                a  COPSDecisionMsg
320      *
321      * @throws   COPSPepException
322      *
323      */
324     protected void processDeleteRequestState(COPSDecisionMsg dMsg)
325     throws COPSPepException {
326         if (_process != null)
327             _process.closeRequestState(this);
328
329         _status = ST_DEL;
330     }
331
332     /**
333      * Process the message SycnStateRequest.
334      * The message SycnStateRequest indicates that the remote PDP
335      * wishes the client (which appears in the common header)
336      * to re-send its state.
337      *
338      * @param    ssMsg               a  COPSSyncStateMsg
339      *
340      * @throws   COPSPepException
341      *
342      */
343     protected void processSyncStateRequest(COPSSyncStateMsg ssMsg)
344     throws COPSPepException {
345         _syncState = false;
346         // If an object for retrieving PEP features exists,
347         // use it for retrieving them
348         final Map<String, String> clientSIs;
349         if (_process != null)
350             clientSIs = _process.getClientData(this);
351         else
352             clientSIs = new HashMap<>();
353
354         // Send request
355         // TODO - do we really want to send the request when the map is empty???
356         _sender.sendRequest(clientSIs);
357
358         _status = ST_SYNC;
359     }
360
361     protected void processClosedConnection(COPSError error)
362     throws COPSPepException {
363         if (_process != null)
364             _process.notifyClosedConnection(this, error);
365
366         _status = ST_CCONN;
367     }
368
369     protected void processNoKAConnection()
370     throws COPSPepException {
371         if (_process != null)
372             _process.notifyNoKAliveReceived(this);
373
374         _status = ST_NOKA;
375     }
376
377     protected void processAcctReport()
378     throws COPSPepException {
379
380         final Map<String, String> report;
381         if (_process != null) report = _process.getAcctData(this);
382         else report = new HashMap<>();
383
384         // TODO - do we really want to send when the map is empty???
385         _sender.sendAcctReport(report);
386
387         _status = ST_ACCT;
388     }
389
390 }