2 * Copyright (c) 2014, 2015 Cable Television Laboratories, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
11 import org.pcmm.gates.IGateID;
12 import org.pcmm.gates.IPCMMGate;
13 import org.pcmm.gates.ITransactionID;
14 import org.pcmm.gates.ITransactionID.GateCommandType;
15 import org.pcmm.gates.impl.PCMMGateReq;
16 import org.pcmm.gates.impl.TransactionID;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19 import org.umu.cops.COPSMsgSender;
20 import org.umu.cops.prpdp.COPSPdpException;
21 import org.umu.cops.stack.*;
22 import org.umu.cops.stack.COPSContext.RType;
23 import org.umu.cops.stack.COPSDecision.Command;
24 import org.umu.cops.stack.COPSDecision.DecisionFlag;
25 import org.umu.cops.stack.COPSHeader.OPCode;
26 import org.umu.cops.stack.COPSObjHeader.CNum;
27 import org.umu.cops.stack.COPSObjHeader.CType;
29 import java.io.IOException;
30 import java.net.Socket;
31 import java.util.HashMap;
32 import java.util.HashSet;
37 * Example of an UNSOLICITED decision
39 * <Gate Control Command> = <COPS Common Header> <Client Handle> <Context> <Decision Flags> <ClientSI Data>
41 * <ClientSI Data> = <Gate-Set> | <Gate-Info> | <Gate-Delete> |
42 * <PDP-Config> | <Synch-Request> | <Msg-Receipt>
43 * <Gate-Set> = <Decision Header> <TransactionID> <AMID> <SubscriberID> [<GateID>] <GateSpec>
44 * <Traffic Profile> <classifier> [<classifier...>] [<Event Generation Info>]
45 * [<Volume-Based Usage Limit>] [<Time-Based Usage Limit>][<Opaque Data>] [<UserID>]
49 * COPS message transceiver class for provisioning connections at the PDP side.
51 public class PCMMPdpMsgSender extends COPSMsgSender {
53 public final static Logger logger = LoggerFactory.getLogger(PCMMPdpMsgSender.class);
54 private static final int MAX_TRANSACTION_ID = 65_536;
56 protected short _transactionID;
57 protected final short _classifierID;
59 // XXX - this does not need to be here
60 protected IGateID _gateID;
63 * Creates a PCMMPdpMsgSender
72 public PCMMPdpMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock) {
73 this(clientType, (short)0, clientHandle, sock);
76 public PCMMPdpMsgSender(final short clientType, final short tID, final COPSHandle clientHandle,
78 super(clientType, clientHandle, sock);
79 _transactionID = tID == 0 ? generateNewTransactionID() : tID;
86 * @return the gate-id value
88 public IGateID getGateID() {
93 * Sends a PCMM GateSet COPS Decision message
94 * @param gate - the gate
95 * @throws COPSPdpException
97 public void sendGateSet(final IPCMMGate gate) throws COPSPdpException {
98 // set transaction ID to gate set
99 // generate a new TransactionID
100 _transactionID = generateNewTransactionID();
101 final ITransactionID trID = new TransactionID(_transactionID, GateCommandType.GATE_SET);
103 gate.setTransactionID(trID);
104 // retain the transactitrIDnumonId to gate request mapping for gateID recovery after response
105 // see PCMMPdpReqStateMan.processReport()
106 final Short trIDnum = trID.getTransactionIdentifier();
107 logger.info("Adding gate to cache - " + gate + " with key - " + (int) (trIDnum & 0xffff));
108 PCMMGlobalConfig.transactionGateMap.put(trIDnum, gate);
110 // new pcmm specific clientsi
111 final byte[] data = gate.getData();
112 // Common Header with the same ClientType as the request
113 // Client Handle with the same clientHandle as the request
115 final Set<COPSDecision> decisionSet = new HashSet<>();
116 decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
117 final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
118 decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
120 final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
121 final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, clientSD);
123 // ** Send the GateSet Decision
125 decisionMsg.writeData(_sock);
126 } catch (IOException e) {
127 logger.error("Failed to send the decision", e);
132 public boolean handleGateReport(final Socket socket) throws COPSPdpException {
134 // waits for the gate-set-ack or error
135 final COPSMsg responseMsg = COPSTransceiver.receiveMsg(socket);
136 if (responseMsg.getHeader().getOpCode().equals(OPCode.RPT)) {
137 logger.info("processing received report from CMTS");
138 final COPSReportMsg reportMsg = (COPSReportMsg) responseMsg;
139 if (reportMsg.getClientSI() == null) {
142 final IPCMMGate responseGate = PCMMGateReq.parse(reportMsg.getClientSI().getData().getData());
143 if (responseGate.getTransactionID() != null
144 && responseGate.getTransactionID().getGateCommandType().equals(GateCommandType.GATE_SET_ACK)) {
145 logger.info("the CMTS has sent a Gate-Set-Ack response");
146 // here CMTS responded that he acknowledged the Gate-Set
147 // TODO do further check of Gate-Set-Ack GateID etc...
148 _gateID = responseGate.getGateID();
155 } catch (Exception e) { // COPSException, IOException
156 throw new COPSPdpException("Error COPSTransceiver.receiveMsg", e);
162 * Sends a message asking that the request state be deleted
164 * @throws COPSPdpException
166 public void sendGateDelete(final IPCMMGate gate) throws COPSPdpException {
167 // set transaction ID to gate set
168 // generate a new TransactionID
169 short _transactionID = generateNewTransactionID();
170 final ITransactionID trID = new TransactionID(_transactionID, GateCommandType.GATE_DELETE);
172 gate.setTransactionID(trID);
174 Short trIDnum = trID.getTransactionIdentifier();
175 PCMMGlobalConfig.transactionGateMap.put(trIDnum, gate);
177 // gateDelete only requires AMID, subscriberID, and gateID
178 // remove the gateSpec, traffic profile, and classifiers from original gate request
179 gate.setGateSpec(null);
180 gate.setTrafficProfile(null);
181 gate.setClassifiers(null);
182 // clear the error object
186 final byte[] data = gate.getData();
187 final Set<COPSDecision> decisionSet = new HashSet<>();
188 decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
189 final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
190 decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
191 final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
193 final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, clientSD);
195 // ** Send the GateDelete Decision
198 decisionMsg.writeData(_sock);
199 // decisionMsg.writeData(socket_id);
200 } catch (IOException e) {
201 logger.error("Failed to send the decision", e);
206 * Sends a request asking that a new request state be created
208 * @throws COPSPdpException
210 public void sendOpenNewRequestState() throws COPSPdpException {
212 * <Decision Message> ::= <Common Header: Flag UNSOLICITED> <Client
213 * Handle> *(<Decision>) [<Integrity>] <Decision> ::= <Context>
214 * <Decision: Flags> <Decision: Flags> ::= Install Request-State
217 final Set<COPSDecision> decisionSet = new HashSet<>();
218 decisionSet.add(new COPSDecision(Command.INSTALL, DecisionFlag.REQSTATE));
219 final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
220 decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
222 final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, null);
225 decisionMsg.writeData(_sock);
226 } catch (IOException e) {
227 throw new COPSPdpException("Failed to send the open new request state", e);
232 * Sends a message asking for a COPS sync operation
234 * @throws COPSPdpException
236 public void sendGateInfo(final IPCMMGate gate) throws COPSPdpException {
238 * <Gate-Info> ::= <Common Header> [<Client Handle>] [<Integrity>]
242 // generate a new TransactionID
243 short _transactionID = generateNewTransactionID();
244 final ITransactionID trID = new TransactionID(_transactionID, GateCommandType.GATE_INFO);
247 gate.setTransactionID(trID);
248 // retain the transactionId to gate request mapping for gateID recovery after response
249 // see PCMMPdpReqStateMan.processReport()
250 final Short trIDnum = trID.getTransactionIdentifier();
251 logger.info("Adding gate to cache - " + gate + " with key - " + (int) (trIDnum & 0xffff));
252 PCMMGlobalConfig.transactionGateMap.put(trIDnum, gate);
254 // gateDelete only requires AMID, subscriberID, and gateID
255 // remove the gateSpec, traffic profile, and classifiers from original gate request
256 gate.setGateSpec(null);
257 gate.setTrafficProfile(null);
258 gate.setClassifiers(null);
259 // clear the error object
264 final byte[] data = gate.getData();
265 final Set<COPSDecision> decisionSet = new HashSet<>();
266 decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
267 final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
268 decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
269 final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
271 //final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), _handle, null);
272 final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, clientSD);
275 //msg.writeData(_sock);
276 decisionMsg.writeData(_sock);
277 } catch (IOException e) {
278 throw new COPSPdpException("Failed to send the GateInfo request", e);
283 * Sends a message asking for a COPS sync operation
285 * @throws COPSPdpException
287 public void sendSyncRequest() throws COPSPdpException {
289 * <Synchronize State Request> ::= <Common Header> [<Client Handle>]
293 // Client Handle with the same clientHandle as the request
294 final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), _handle, null);
296 msg.writeData(_sock);
297 } catch (IOException e) {
298 throw new COPSPdpException("Failed to send the sync state request", e);
302 public void sendSyncRequestState() throws COPSPdpException {
305 public void sendDeleteRequestState() throws COPSPdpException {
307 private static short generateNewTransactionID() {
308 return (short) (Math.random() * MAX_TRANSACTION_ID);