fixed usage of optional and fixed bug in ccap validator test
[packetcable.git] / packetcable-emulator / src / main / java / org / pcmm / rcd / impl / CmtsPepReqStateMan.java
1 /*
2  * (c) 2015 Cable Television Laboratories, Inc.  All rights reserved.
3  */
4
5 package org.pcmm.rcd.impl;
6
7 import org.pcmm.gates.IGateSpec.Direction;
8 import org.pcmm.gates.IPCMMError;
9 import org.pcmm.gates.IPCMMError.ErrorCode;
10 import org.pcmm.gates.impl.GateID;
11 import org.pcmm.gates.impl.PCMMError;
12 import org.pcmm.gates.impl.PCMMGateReq;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15 import org.umu.cops.prpep.COPSPepException;
16 import org.umu.cops.prpep.COPSPepMsgSender;
17 import org.umu.cops.prpep.COPSPepReqStateMan;
18 import org.umu.cops.stack.*;
19 import org.umu.cops.stack.COPSDecision.DecisionFlag;
20 import org.umu.cops.stack.COPSObjHeader.CNum;
21 import org.umu.cops.stack.COPSObjHeader.CType;
22 import org.umu.cops.stack.COPSReportType.ReportType;
23
24 import java.io.IOException;
25 import java.net.Socket;
26 import java.util.*;
27
28 /**
29  * PEP State manager implementation for use in a CMTS.
30  */
31 public class CmtsPepReqStateMan extends COPSPepReqStateMan {
32
33     private final static Logger logger = LoggerFactory.getLogger(CmtsPepReqStateMan.class);
34
35     /**
36      * The configured gates
37      */
38     private final Map<Direction, Set<String>> gateConfig;
39
40     /**
41      * The connected CMTSs and whether or not they are up
42      */
43     private final Map<String, Boolean> cmStatus;
44
45     /**
46      * Contains the gates that have been set where the key is the gate name and the value is a Set of subIds
47      * that are using this gate
48      */
49     private final Map<String, Set<String>> gatesSetMap;
50
51     /**
52      * Create a State Request Manager
53      *
54      * @param clientType - the client type for this connection
55      * @param clientHandle - the client-handle for this connection
56      * @param process - the data processor
57      * @param socket - the socket connection
58      * @param gateConfig - the configured service class names (gates)
59      */
60     public CmtsPepReqStateMan(final short clientType, final COPSHandle clientHandle, final CmtsDataProcessor process,
61                               final Socket socket, final Map<Direction, Set<String>> gateConfig,
62                               final Map<String, Boolean> cmStatus) {
63         super(clientType, clientHandle, process, socket, new COPSPepMsgSender(clientType, clientHandle, socket));
64         this.gateConfig = Collections.unmodifiableMap(gateConfig);
65         this.cmStatus = Collections.unmodifiableMap(cmStatus);
66
67         this.gatesSetMap = new HashMap<>();
68         for (final Set<String> gateIdSet: gateConfig.values()) {
69             for (final String gateId : gateIdSet) {
70                 gatesSetMap.put(gateId, new HashSet<String>());
71             }
72         }
73     }
74
75     @Override
76     protected void processDecision(final COPSDecisionMsg dMsg) throws COPSException {
77         logger.info("Processing decision message - " + dMsg);
78         final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
79
80         final Map<String, String> removeDecs = new HashMap<>();
81         final Map<String, String> installDecs = new HashMap<>();
82
83         for (final Set<COPSDecision> copsDecisions: decisions.values()) {
84             final COPSDecision cmddecision = copsDecisions.iterator().next();
85             switch (cmddecision.getCommand()) {
86                 case INSTALL:
87                     for (final COPSDecision decision : copsDecisions) {
88                         if (decision.getFlag().equals(DecisionFlag.REQERROR)) {
89                             logger.info("processing decision");
90                             // This is assuming a gate set right or wrong
91                             if (dMsg.getDecisions().size() == 1 && dMsg.getDecSI() != null) {
92                                 final PCMMGateReq gateReq = PCMMGateReq.parse(dMsg.getDecSI().getData().getData());
93                                 if (gateReq.getGateSpec() != null) {
94                                     processGateReq(gateReq, _socket);
95                                 }
96                             }
97                         }
98                     }
99                     break;
100                 case REMOVE:
101                     for (final COPSDecision decision : copsDecisions) {
102                         // TODO - implement gate delete
103                     }
104                     break;
105             }
106
107         }
108
109         //** Apply decisions to the configuration
110         // TODO - why is this collection never getting populated???
111         final Map<String, String> errorDecs = new HashMap<>();
112         _process.setDecisions(this, removeDecs, installDecs, errorDecs);
113         _status = Status.ST_DECS;
114
115
116         if (_process.isFailReport(this)) {
117             // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
118             _sender.sendFailReport(_process.getReportData(this));
119         } else {
120             // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
121             _sender.sendSuccessReport(_process.getReportData(this));
122         }
123         _status = Status.ST_REPORT;
124
125         if (!_syncState) {
126             _sender.sendSyncComplete();
127             _syncState = true;
128             _status = Status.ST_SYNCALL;
129         }
130     }
131
132     private void processGateReq(final PCMMGateReq gateReq, final Socket socket) throws COPSException {
133         // TODO - Check and/or Set state here
134         // Gate ADD gateReq.getTrafficProfile() != null
135         // Gate REMOVE gateReq.getTrafficProfile() == null
136         final String subId = gateReq.getSubscriberID().getSourceIPAddress().getHostAddress();
137
138         // Get direction here
139         final Direction gateDir = gateReq.getGateSpec().getDirection();
140         final Set<String> gateNames = gateConfig.get(gateDir);
141         // TODO - Determine if this is the best means to derive the gate name???
142         final String gateName = new String(gateReq.getTrafficProfile().getAsBinaryArray());
143
144         final IPCMMError error;
145         if (subId == null || gateDir == null || gateNames == null) {
146             // Missing required object
147             // TODO - Determine if this is the correct code. 3 was being used previously and I don't see any corresponding code.
148             error = new PCMMError(ErrorCode.UNK_GATE_ID);
149         } else if (!cmStatus.keySet().contains(subId)
150                 || (cmStatus.keySet().contains(subId) && !cmStatus.get(subId))) {
151             // Invalid Object
152             // TODO - Determine if this code is correct
153             error = new PCMMError(ErrorCode.INVALID_SUB_ID);
154         } else if (!gateNames.contains(gateName.trim())) {
155             // TODO - Determine if this code is correct
156             error = new PCMMError(ErrorCode.UNDEF_SCN_NAME);
157         } else {
158             error = null;
159             gatesSetMap.get(gateName.trim()).add(subId);
160         }
161         gateReq.setError(error);
162
163         logger.info("Processing gate request [" + gateName + "] with direction [" + gateDir + ']');
164
165         // Get gate name
166
167         // Set response
168         final List<Byte> data = new ArrayList<>();
169         for (final byte val : gateReq.getTransactionID().getAsBinaryArray())
170             data.add(val);
171         for (final byte val : gateReq.getAMID().getAsBinaryArray())
172             data.add(val);
173         for (final byte val : gateReq.getSubscriberID().getAsBinaryArray())
174             data.add(val);
175         if (error != null) for (final byte val : gateReq.getError().getAsBinaryArray())
176             data.add(val);
177
178         // Assign a gate ID
179         final GateID gateID = new GateID(UUID.randomUUID().hashCode());
180         for (final byte val : gateID.getAsBinaryArray())
181             data.add(val);
182
183
184         final byte[] csiArr = new byte[data.size()];
185         for (int i = 0; i < data.size(); i++) {
186             csiArr[i] = data.get(i);
187         }
188         final COPSClientSI si = new COPSClientSI(CNum.CSI, CType.DEF, new COPSData(csiArr, 0, csiArr.length));
189
190         final ReportType reportType;
191         if (gateReq.getError() == null) reportType = ReportType.SUCCESS; else reportType = ReportType.FAILURE;
192
193         logger.info("Returning " + reportType + " for gate request [" + gateName + "] direction [" + gateDir
194                 + "] for host - " + subId);
195         final COPSReportMsg reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
196                     new COPSReportType(reportType), si, null);
197         try {
198             reportMsg.writeData(socket);
199         } catch (IOException e) {
200             throw new COPSPepException("Error writing gate set SUCCESS Report", e);
201         }
202     }
203
204 }