Cleanup of state managers' interfaces (constructor and init).
[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.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11 import org.umu.cops.COPSStateMan;
12 import org.umu.cops.stack.*;
13
14 import java.net.Socket;
15 import java.util.HashMap;
16 import java.util.Map;
17 import java.util.Set;
18
19 /**
20  * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
21  * in PEP.
22  *
23  *   The client handle is used to identify a unique request state for a
24  *   single PEP per client-type. Client handles are chosen by the PEP and
25  *   are opaque to the PDP. The PDP simply uses the request handle to
26  *   uniquely identify the request state for a particular Client-Type over
27  *   a particular TCP connection and generically tie its decisions to a
28  *   corresponding request. Client handles are initiated in request
29  *   messages and are then used by subsequent request, decision, and
30  *   report messages to reference the same request state. When the PEP is
31  *   ready to remove a local request state, it will issue a delete message
32  *   to the PDP for the corresponding client handle. A handle MUST be
33  *   explicitly deleted by the PEP before it can be used by the PEP to
34  *   identify a new request state. Handles referring to different request
35  *   states MUST be unique within the context of a particular TCP
36  *   connection and client-type.
37  *
38  * @version COPSPepReqStateMan.java, v 2.00 2004
39  *
40  */
41 public class COPSPepReqStateMan extends COPSStateMan {
42
43     private final static Logger logger = LoggerFactory.getLogger(COPSPepReqStateMan.class);
44
45     /**
46         The PolicyDataProcess is used to process policy data in the PEP
47      */
48     protected final COPSPepDataProcess _process;
49
50     /**
51         The Msg Sender is used to send COPS messages
52      */
53     private final COPSPepMsgSender _sender;
54
55     /**
56      * Sync State
57      */
58     protected transient boolean _syncState;
59
60     /**
61      * Constructor for this class
62      * @param clientType - the PEP client type
63      * @param clientHandle - the client-handle
64      * @param process - the data processor
65      * @param socket - the socket connection
66      */
67     public COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPepDataProcess process,
68                               final Socket socket) {
69         this(clientType, clientHandle, process, socket, new COPSPepMsgSender(clientType, clientHandle, socket));
70     }
71
72     /**
73      * Constructor for sub-classes
74      * @param clientType - the PEP client type
75      * @param clientHandle - the client-handle
76      * @param process - the data processor
77      * @param socket - the socket connection
78      * @param sender - responsible for sending COPS messages to the PEP
79      */
80     protected COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPepDataProcess process,
81                                  final Socket socket, final COPSPepMsgSender sender) {
82
83         super(clientType, clientHandle, socket);
84         this._process = process;
85         _syncState = true;
86         // Inits an object for sending COPS messages to the PDP
87         _sender = sender;
88     }
89
90     /**
91      * Init Request State
92      * @throws   COPSPepException
93      */
94     public void initRequestState() throws COPSException {
95         // If an object for retrieving PEP features exists,
96         // use it for retrieving them
97         final Map<String, String> clientSIs;
98         if (_process != null)
99             clientSIs = _process.getClientData(this);
100         else
101             clientSIs = new HashMap<>();
102
103         // Send the request
104         // TODO - do we really want to send when this is empty???
105         _sender.sendRequest(clientSIs);
106
107         // Initial state
108         _status = Status.ST_INIT;
109     }
110
111     /**
112      * Finalize Request State
113      *
114      * @throws   COPSPepException
115      *
116      */
117     public void finalizeRequestState() throws COPSException {
118         _sender.sendDeleteRequest();
119         _status = Status.ST_FINAL;
120     }
121
122     /**
123      * Process the message Decision
124      * @param    dMsg                a  COPSDecisionMsg
125      * @throws   COPSPepException
126      */
127     protected void processDecision(final COPSDecisionMsg dMsg) throws COPSException {
128         logger.info("Processing decision message - " + dMsg);
129         final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
130
131         final Map<String, String> removeDecs = new HashMap<>();
132         final Map<String, String> installDecs = new HashMap<>();
133
134         for (final Set<COPSDecision> copsDecisions: decisions.values()) {
135             final COPSDecision cmddecision = copsDecisions.iterator().next();
136             String prid = "";
137             switch (cmddecision.getCommand()) {
138                 case INSTALL:
139                     for (final COPSDecision decision : copsDecisions) {
140                         final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
141                         switch (obj.getSNum()) {
142                             case COPSPrObjBase.PR_PRID:
143                                 prid = obj.getData().str();
144                                 break;
145                             case COPSPrObjBase.PR_EPD:
146                                 installDecs.put(prid, obj.getData().str());
147                                 break;
148                             default:
149                                 break;
150                         }
151                     }
152                     break;
153                 case REMOVE:
154                     for (final COPSDecision decision : copsDecisions) {
155                         final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
156                         switch (obj.getSNum()) {
157                             case COPSPrObjBase.PR_PRID:
158                                 prid = obj.getData().str();
159                                 break;
160                             case COPSPrObjBase.PR_EPD:
161                                 removeDecs.put(prid, obj.getData().str());
162                                 break;
163                             default:
164                                 break;
165                         }
166                     }
167                     break;
168             }
169
170         }
171
172         //** Apply decisions to the configuration
173         // TODO - why is this collection never getting populated???
174         final Map<String, String> errorDecs = new HashMap<>();
175         _process.setDecisions(this, removeDecs, installDecs, errorDecs);
176         _status = Status.ST_DECS;
177
178
179         if (_process.isFailReport(this)) {
180             logger.info("Sending FAIL report");
181             _sender.sendFailReport(_process.getReportData(this));
182         } else {
183             logger.info("Sending SUCCESS report");
184             _sender.sendSuccessReport(_process.getReportData(this));
185         }
186         _status = Status.ST_REPORT;
187
188         if (!_syncState) {
189             _sender.sendSyncComplete();
190             _syncState = true;
191             _status = Status.ST_SYNCALL;
192         }
193     }
194
195     /**
196      * Process the message NewRequestState
197      * @throws   COPSPepException
198      */
199     protected void processOpenNewRequestState() throws COPSPepException {
200         if (_process != null)
201             _process.newRequestState(this);
202
203         _status = Status.ST_NEW;
204     }
205
206     /**
207      * Process the message DeleteRequestState
208      * @param    dMsg                a  COPSDecisionMsg
209      * @throws   COPSPepException
210      */
211     protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
212         if (_process != null)
213             _process.closeRequestState(this);
214
215         _status = Status.ST_DEL;
216     }
217
218     /**
219      * Process the message SycnStateRequest.
220      * The message SycnStateRequest indicates that the remote PDP
221      * wishes the client (which appears in the common header)
222      * to re-send its state.
223      * @param    ssMsg               a  COPSSyncStateMsg
224      * @throws   COPSPepException
225      */
226     protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSException {
227         _syncState = false;
228         // If an object for retrieving PEP features exists,
229         // use it for retrieving them
230         final Map<String, String> clientSIs;
231         if (_process != null)
232             clientSIs = _process.getClientData(this);
233         else
234             clientSIs = new HashMap<>();
235
236         // Send request
237         // TODO - do we really want to send the request when the map is empty???
238         _sender.sendRequest(clientSIs);
239
240         _status = Status.ST_SYNC;
241     }
242
243     public void processClosedConnection(final COPSError error) throws COPSPepException {
244         if (_process != null)
245             _process.notifyClosedConnection(this, error);
246
247         _status = Status.ST_CCONN;
248     }
249
250     public void processNoKAConnection() throws COPSException {
251         if (_process != null)
252             _process.notifyNoKAliveReceived(this);
253
254         _status = Status.ST_NOKA;
255     }
256
257     /**
258      * Creates and sends an accounting report
259      * @throws COPSException
260      */
261     public void processAcctReport() throws COPSException {
262         final Map<String, String> report;
263         if (_process != null) report = _process.getAcctData(this);
264         else report = new HashMap<>();
265
266         // TODO - do we really want to send when the map is empty???
267         _sender.sendAcctReport(report);
268
269         _status = Status.ST_ACCT;
270     }
271
272 }