7 import org.pcmm.objects.MMVersionInfo;
8 import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory;
10 import org.umu.cops.prpdp.COPSPdpAgent;
11 import org.umu.cops.prpdp.COPSPdpException;
12 import org.umu.cops.stack.*;
13 import org.umu.cops.stack.COPSError.ErrorTypes;
14 import org.umu.cops.stack.COPSHeader.OPCode;
16 import java.io.IOException;
17 import java.net.InetAddress;
18 import java.net.Socket;
21 * Core PDP agent for provisioning
23 public class PCMMPdpAgent extends COPSPdpAgent {
25 private static final Logger logger = LoggerFactory.getLogger(PCMMPdpAgent.class);
27 /** Well-known port for PCMM */
28 public static final int WELL_KNOWN_PDP_PORT = 3918;
33 private final String psHost;
38 private final int psPort;
41 * Policy data processing object
43 private final PCMMPdpDataProcess _process;
45 // Next two attributes are initialized when connected
47 * The Socket connection to the PEP
49 private transient Socket socket;
50 private transient COPSHandle _handle;
55 * @param clientType - COPS Client-type
56 * @param psHost - Host to connect to
57 * @param psPort - Port to connect to
58 * @param process - Object to perform policy data processing
60 public PCMMPdpAgent(final short clientType, final String psHost, final int psPort,
61 final PCMMPdpDataProcess process) {
62 super(psPort, clientType, null);
63 this._process = process;
69 * XXX -tek- This is the retooled connect. Not sure if the while forever
70 * loop is needed. Socket accept --> handleClientOpenMsg --> pdpConn.run()
72 * Below is new Thread(pdpConn).start(); Does that do it?
78 * @return <tt>true</tt> if PDP accepts the connection; <tt>false</tt>
80 * @throws java.net.UnknownHostException
81 * @throws java.io.IOException
82 * @throws COPSException
84 public boolean connect() throws IOException, COPSException, COPSPdpException {
85 // Create Socket and send OPN
86 final InetAddress addr = InetAddress.getByName(psHost);
87 // caller will catch IOExceptions
88 socket = new Socket(addr, psPort);
89 logger.debug("{} {}", getClass().getName(), "PDP Socket Opened");
90 // COPSDebug.err(getClass().getName(), "PDP Socket Opened");
91 // Loop through for Incoming messages
93 // server infinite loop
97 // We're waiting for an message
99 logger.debug("Waiting to receiveMsg");
100 final COPSMsg msg = COPSTransceiver.receiveMsg(socket);
101 logger.debug("Message received of type - " + msg.getHeader().getOpCode());
102 if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
103 handleClientOpenMsg(socket, msg);
107 } catch (Exception ex) {
108 logger.error("Unexpected error closing socket", ex);
111 } catch (Exception e) {
112 logger.error("Unexpected error handing client open message", e);
115 } catch (Exception ex) {
116 logger.error("Unexpected error closing socket", ex);
124 // TODO - remove and let super handle after DataProcess & PdpConnection classes are properly refactored
126 public void disconnect (final String pepID, final COPSError error) throws COPSException, IOException {
127 final PCMMPdpConnection pdpConn = (PCMMPdpConnection) _connectionMap.get(pepID);
128 if (pdpConn != null) {
129 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(), error, null, null);
130 closeMsg.writeData(pdpConn.getSocket());
134 final Thread thread = threadMap.remove(pepID);
135 if (thread != null) thread.interrupt();
139 protected void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
140 logger.info("Processing client open message");
141 final COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
142 _pepId = cMsg.getPepId();
144 // Validate Client Type
145 // TODO - Need to fix this logic. Currently the client type being set is the CCAP AMID.type mapped to the
146 // enumeration's ordinal value
148 if (msg.getHeader().getClientType() != getClientType()) {
149 // Unsupported client type
150 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
151 new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
153 closeMsg.writeData(conn);
154 } catch (IOException unae) {
155 logger.error("Unexpected error writing data", unae);
158 throw new COPSException("Unsupported client type");
162 // PEPId is mandatory
163 if (_pepId == null) {
164 // Mandatory COPS object missing
165 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
166 new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
168 closeMsg.writeData(conn);
169 } catch (IOException unae) {
170 logger.error("Unexpected error closing socket", unae);
173 throw new COPSException("Mandatory COPS object missing (PEPId)");
177 if ((cMsg.getClientSI() != null) ) {
178 final MMVersionInfo _mminfo = new MMVersionInfo(cMsg.getClientSI().getData().getData());
179 logger.debug("CMTS sent MMVersion info : major:" + _mminfo.getMajorVersionNB() + " minor:" +
180 _mminfo.getMinorVersionNB());
183 // Unsupported objects
184 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
185 new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
187 closeMsg.writeData(conn);
188 } catch (IOException unae) {
189 logger.error("Unexpected error writing data", unae);
192 throw new COPSException("Unsupported objects (PdpAddress, Integrity)");
197 // Connection accepted
198 final COPSClientAcceptMsg acceptMsg;
199 if (getAcctTimer() != 0)
200 acceptMsg = new COPSClientAcceptMsg(getClientType(), new COPSKATimer(getKaTimer()),
201 new COPSAcctTimer(getAcctTimer()), null);
203 acceptMsg = new COPSClientAcceptMsg(getClientType(), new COPSKATimer(getKaTimer()), null, null);
204 acceptMsg.writeData(conn);
205 // XXX - handleRequestMsg
207 logger.debug("handleClientOpenMsg() - Waiting to receive message");
208 final COPSMsg rmsg = COPSTransceiver.receiveMsg(socket);
209 logger.debug("Received message of type - " + rmsg.getHeader().getOpCode());
211 if (rmsg.getHeader().getOpCode().equals(OPCode.CC)) {
212 System.out.println(((COPSClientCloseMsg) rmsg)
213 .getError().getDescription());
215 final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
216 new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
218 closeMsg.writeData(conn);
219 } catch (IOException unae) {
220 logger.error("Unexpected error writing data", unae);
222 throw new COPSException("CMTS requetsed Client-Close");
225 if (rmsg.getHeader().getOpCode().equals(OPCode.REQ)) {
226 COPSReqMsg rMsg = (COPSReqMsg) rmsg;
227 _handle = rMsg.getClientHandle();
229 throw new COPSException("Can't understand request");
231 } catch (Exception e) { // COPSException, IOException
232 throw new COPSException("Error COPSTransceiver.receiveMsg", e);
235 logger.debug("PDPCOPSConnection");
236 final PCMMPdpConnection pdpConn = new PCMMPdpConnection(_pepId, conn, _process);
237 pdpConn.setKaTimer(getKaTimer());
238 if (getAcctTimer() != 0)
239 pdpConn.setAccTimer(getAcctTimer());
241 // XXX - handleRequestMsg
242 // XXX - check handle is valid
243 final PCMMPdpReqStateMan man = new PCMMPdpReqStateMan(getClientType(), _handle.getId().str());
244 pdpConn.addStateMan(_handle.getId().str(), man);
245 man.setDataProcess(_process);
247 man.initRequestState(conn);
248 } catch (COPSPdpException unae) {
249 logger.error("Unexpected error initializing state", unae);
251 // XXX - End handleRequestMsg
253 logger.info("Starting PDP connection thread to - " + psHost);
255 // TODO - store the thread reference so it is possible to manage.
256 final Thread thread = new Thread(pdpConn, "Agent for - " + psHost);
258 threadMap.put(_pepId.getData().str(), thread);
259 _connectionMap.put(_pepId.getData().str(), pdpConn);
262 public Socket getSocket() {
265 public PCMMPdpDataProcess getProcess() {
268 public COPSHandle getClientHandle() {
271 public String getPepIdString() {
272 return _pepId.getData().str();
278 * @see org.pcmm.rcd.IPCMMClient#isConnected()
280 public boolean isConnected() {
281 return socket != null && socket.isConnected();