-/*\r
- * Copyright (c) 2003 University of Murcia. All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.stack;\r
-\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.Socket;\r
-\r
-/**\r
- * COPS Header (RFC 2748 pag. 6)\r
- *\r
- * Each COPS message consists of the COPS header followed by a number of\r
- * typed objects.\r
- *\r
- * 0 1 2 3\r
- * +--------------+--------------+--------------+--------------+\r
- * |Version| Flags| Op Code | Client-type |\r
- * +--------------+--------------+--------------+--------------+\r
- * | Message Length |\r
- * +--------------+--------------+--------------+--------------+\r
- *\r
- * Global note: //// implies field is reserved, set to 0.\r
- *\r
- * The fields in the header are:\r
- * Version: 4 bits\r
- * COPS version number. Current version is 1.\r
- *\r
- * Flags: 4 bits\r
- * Defined flag values (all other flags MUST be set to 0):\r
- * 0x1 Solicited Message Flag Bit\r
- * This flag is set when the message is solicited by\r
- * another COPS message. This flag is NOT to be set\r
- * (value=0) unless otherwise specified.\r
- *\r
- * Op Code: 8 bits\r
- * The COPS operations:\r
- * 1 = Request (REQ)\r
- * 2 = Decision (DEC)\r
- * 3 = Report State (RPT)\r
- * 4 = Delete Request State (DRQ)\r
- * 5 = Synchronize State Req (SSQ)\r
- * 6 = Client-Open (OPN)\r
- * 7 = Client-Accept (CAT)\r
- * 8 = Client-Close (CC)\r
- * 9 = Keep-Alive (KA)\r
- * 10= Synchronize Complete (SSC)\r
- *\r
- * Client-type: 16 bits\r
- *\r
- *\r
- * @version COPSHeader.java, v 1.00 2003\r
- *\r
- */\r
-public class COPSHeader {\r
-\r
- public final static byte COPS_OP_REQ = 1;\r
- public final static byte COPS_OP_DEC = 2;\r
- public final static byte COPS_OP_RPT = 3;\r
- public final static byte COPS_OP_DRQ = 4;\r
- public final static byte COPS_OP_SSQ = 5;\r
- public final static byte COPS_OP_OPN = 6;\r
- public final static byte COPS_OP_CAT = 7;\r
- public final static byte COPS_OP_CC = 8;\r
- public final static byte COPS_OP_KA = 9;\r
- public final static byte COPS_OP_SSC = 10;\r
-\r
- public final static byte COPS_FLAG_NULL = 0;\r
- public final static byte COPS_FLAG_SOLICITED = 1;\r
-\r
- private byte _versionNflg;\r
- private byte _opCode;\r
- private short _cType;\r
- private int _msgLength;\r
-\r
- public COPSHeader() {\r
- _versionNflg = 0x10;\r
- _opCode = 0;\r
- _cType = 0;\r
- _msgLength = 0;\r
- }\r
-\r
- public COPSHeader(byte opCode, short clientType) {\r
- _versionNflg = 0x10;\r
- _opCode = opCode;\r
- _cType = clientType;\r
- _msgLength = 0;\r
- if (isAKeepAlive()) _cType = 0;\r
- }\r
-\r
- public COPSHeader(byte opCode) {\r
- _versionNflg = 0x10;\r
- _opCode = opCode;\r
- _cType = 0;\r
- _msgLength = 0;\r
- if (isAKeepAlive()) _cType = 0;\r
- }\r
-\r
- /**\r
- Parse data and create COPSHeader object\r
- */\r
- public COPSHeader(byte[] buf) {\r
- _versionNflg = (byte) buf[0];\r
- _opCode = (byte) buf[1];\r
- _cType |= ((short) buf[2]) << 8;\r
- _cType |= ((short) buf[3]) & 0xFF;\r
- _msgLength |= ((short) buf[4]) << 24;\r
- _msgLength |= ((short) buf[5]) << 16;\r
- _msgLength |= ((short) buf[6]) << 8;\r
- _msgLength |= ((short) buf[7]) & 0xFF;\r
- }\r
-\r
- /**\r
- * If the operation code corresponds with a message Request, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isARequest() {\r
- return (_opCode == COPS_OP_REQ);\r
- }\r
-\r
- /**\r
- * If the operation code corresponds with a message Decision, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isADecision() {\r
- return (_opCode == COPS_OP_DEC);\r
- }\r
-\r
- /**\r
- * If the operation code corresponds with a message Report, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isAReport() {\r
- return (_opCode == COPS_OP_RPT);\r
- }\r
-\r
- /**\r
- * If the operation code corresponds with a message DeleteRequest, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isADeleteReq() {\r
- return (_opCode == COPS_OP_DRQ);\r
- }\r
-\r
- /**\r
- * If the operation code corresponds with a message SyncStateReq, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isASyncStateReq() {\r
- return (_opCode == COPS_OP_SSQ);\r
- }\r
-\r
- /**\r
- * If the operation code corresponds with a message ClientOpen, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isAClientOpen() {\r
- return (_opCode == COPS_OP_OPN);\r
- }\r
-\r
- /**\r
- * If the operation code corresponds with a message ClientAccept, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isAClientAccept() {\r
- return (_opCode == COPS_OP_CAT);\r
- }\r
-\r
- /**\r
- * If operation code corresponds with a message ClientClose, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isAClientClose() {\r
- return (_opCode == COPS_OP_CC);\r
- }\r
-\r
- /**\r
- * If the operation code corresponds with a message KeepAlive, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isAKeepAlive() {\r
- return (_opCode == COPS_OP_KA);\r
- }\r
-\r
- /**\r
- * If the operation code corresponds with a message SSC, return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isASyncComplete() {\r
- return (_opCode == COPS_OP_SSC);\r
- }\r
-\r
- /**\r
- * Get message length\r
- *\r
- * @return an int\r
- *\r
- */\r
- public int getMsgLength() {\r
- return _msgLength;\r
- }\r
-\r
- /**\r
- * Get header length\r
- *\r
- * @return an int\r
- *\r
- */\r
- public int getHdrLength() {\r
- // return (sizeof(u_int32_t) * 2);\r
- return ( 8 );\r
- }\r
-\r
- /**\r
- * Get Operation Code\r
- *\r
- * @return a byte\r
- *\r
- */\r
- public byte getOpCode() {\r
- return _opCode;\r
- }\r
-\r
- /**\r
- * Set the solicitation flag\r
- *\r
- * @param flg a byte\r
- *\r
- */\r
- public void setFlag(byte flg) {\r
- _versionNflg &= 0x10;\r
- _versionNflg |= flg;\r
- }\r
-\r
- /**\r
- * Returns the flags field\r
- * @return aByte Flags field in header\r
- */\r
- public byte getFlags() { //OJO\r
- return (byte) (_versionNflg & 0x0f);\r
- }\r
-\r
- /**\r
- * Set the client-type\r
- *\r
- * @param cType a short\r
- *\r
- */\r
- public void setClientType(short cType) {\r
- _cType = cType;\r
- };\r
-\r
- /**\r
- * Set the message length\r
- *\r
- * @param len an int\r
- *\r
- * @throws COPSException\r
- *\r
- */\r
- public void setMsgLength(int len) throws COPSException {\r
- if ((len % 4) != 0)\r
- throw new COPSException ("Message is not aligned on 32 bit intervals");\r
- _msgLength = len + 8;\r
- }\r
-\r
- /**\r
- * Get client-type\r
- *\r
- * @return a short\r
- *\r
- */\r
- public short getClientType() {\r
- return (_cType);\r
- };\r
-\r
- /**\r
- * Always return true\r
- *\r
- * @return a boolean\r
- *\r
- */\r
- public boolean isCOPSHeader() {\r
- return true;\r
- };\r
-\r
- /**\r
- * Writes object to given network socket in network byte order\r
- *\r
- * @param id a Socket\r
- *\r
- * @throws IOException\r
- *\r
- */\r
- public void writeData(Socket id) throws IOException {\r
- byte buf[] = new byte[8];\r
-\r
- buf[0] = (byte) _versionNflg;\r
- buf[1] = (byte) _opCode;\r
- buf[2] = (byte) (_cType >> 8);\r
- buf[3] = (byte) _cType;\r
- buf[4] = (byte) (_msgLength >> 24);\r
- buf[5] = (byte) (_msgLength >> 16);\r
- buf[6] = (byte) (_msgLength >> 8);\r
- buf[7] = (byte) _msgLength;\r
-\r
- COPSUtil.writeData(id, buf, 8);\r
- }\r
-\r
- /**\r
- * Get an object textual description\r
- *\r
- * @return a String\r
- *\r
- */\r
- public String toString() {\r
- String str = new String();\r
-\r
- str += "**MSG HEADER** \n";\r
- str += "Version: " + (_versionNflg >> 4) + "\n";\r
- str += "Flags: " + (_versionNflg & 0x01) + "\n";\r
- str += "OpCode: " + _opCode + "\n";\r
- str += "Client-type: " + _cType + "\n";\r
- str += "Message-length(bytes): " + _msgLength + "\n";\r
- return str;\r
- }\r
-\r
- /**\r
- * Write an object textual description in the output stream\r
- *\r
- * @param os an OutputStream\r
- *\r
- * @throws IOException\r
- *\r
- */\r
- public void dump(OutputStream os) throws IOException {\r
- os.write(new String("**MSG HEADER**" + "\n").getBytes());\r
- os.write(new String("Version: " + (_versionNflg >> 4) + "\n").getBytes());\r
- os.write(new String("Flags: " + (_versionNflg & 0x01) + "\n").getBytes());\r
- os.write(new String("OpCode: " + _opCode + "\n").getBytes());\r
- os.write(new String("Client-type: " + _cType + "\n").getBytes());\r
- os.write(new String("Message-length(bytes): " + _msgLength + "\n").getBytes());\r
- }\r
-}\r
-\r
-\r
-\r
-\r
+/*
+ * Copyright (c) 2003 University of Murcia. All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.stack;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * COPS Header (RFC 2748 pag. 6)
+ *
+ * Each COPS message consists of the COPS header followed by a number of
+ * typed objects.
+ *
+ * 0 1 2 3
+ * +--------------+--------------+--------------+--------------+
+ * |Version| Flags| Op Code | Client-type |
+ * +--------------+--------------+--------------+--------------+
+ * | Message Length |
+ * +--------------+--------------+--------------+--------------+
+ *
+ * Global note: //// implies field is reserved, set to 0.
+ *
+ * The fields in the header are:
+ * Version: 4 bits
+ * COPS version number. Current version is 1.
+ *
+ * Flags: 4 bits
+ * Defined flag values (all other flags MUST be set to 0):
+ * 0x1 Solicited Message Flag Bit
+ * This flag is set when the message is solicited by
+ * another COPS message. This flag is NOT to be set
+ * (value=0) unless otherwise specified.
+ *
+ * Op Code: 8 bits
+ * The COPS operations:
+ * 1 = Request (REQ)
+ * 2 = Decision (DEC)
+ * 3 = Report State (RPT)
+ * 4 = Delete Request State (DRQ)
+ * 5 = Synchronize State Req (SSQ)
+ * 6 = Client-Open (OPN)
+ * 7 = Client-Accept (CAT)
+ * 8 = Client-Close (CC)
+ * 9 = Keep-Alive (KA)
+ * 10= Synchronize Complete (SSC)
+ *
+ * Client-type: 16 bits
+ *
+ *
+ * @version COPSHeader.java, v 1.00 2003
+ *
+ */
+public class COPSHeader {
+
+ /**
+ * Map allowing for the quick retrieval of the client type based on the numeric value coming in via the
+ * COPS payload.
+ */
+ final static Map<Integer, ClientType> VAL_TO_CT = new ConcurrentHashMap<>();
+ static {
+ VAL_TO_CT.put(ClientType.NA.ordinal(), ClientType.NA);
+ VAL_TO_CT.put(ClientType.TYPE_1.ordinal(), ClientType.TYPE_1);
+ VAL_TO_CT.put(ClientType.TYPE_2.ordinal(), ClientType.TYPE_2);
+ VAL_TO_CT.put(ClientType.TYPE_3.ordinal(), ClientType.TYPE_3);
+ }
+
+ /**
+ * Map allowing for the quick retrieval of the operation based on the numeric value coming in via the
+ * COPS payload.
+ */
+ final static Map<Integer, OPCode> VAL_TO_OP = new ConcurrentHashMap<>();
+ static {
+ VAL_TO_OP.put(OPCode.NA.ordinal(), OPCode.NA);
+ VAL_TO_OP.put(OPCode.REQ.ordinal(), OPCode.REQ);
+ VAL_TO_OP.put(OPCode.DEC.ordinal(), OPCode.DEC);
+ VAL_TO_OP.put(OPCode.RPT.ordinal(), OPCode.RPT);
+ VAL_TO_OP.put(OPCode.DRQ.ordinal(), OPCode.DRQ);
+ VAL_TO_OP.put(OPCode.SSQ.ordinal(), OPCode.SSQ);
+ VAL_TO_OP.put(OPCode.OPN.ordinal(), OPCode.OPN);
+ VAL_TO_OP.put(OPCode.CAT.ordinal(), OPCode.CAT);
+ VAL_TO_OP.put(OPCode.CC.ordinal(), OPCode.CC);
+ VAL_TO_OP.put(OPCode.KA.ordinal(), OPCode.KA);
+ VAL_TO_OP.put(OPCode.SSC.ordinal(), OPCode.SSC);
+ }
+
+ /**
+ * Represents the PCMM version number of the message
+ * Holds the first nibble of the COPS message
+ */
+ private final int _pcmmVersion;
+
+ /**
+ * Represents the second nibble of the message where solicited decisions will be set to 1 else 0
+ * Values 0 = UNSOLICITED | 1 = SOLICITED
+ */
+ private final Flag _flag;
+
+ /**
+ * Represents the type of operation which will be used to determine the type of COPSMsg this header will be a
+ * part of.
+ * Uses the byte value contained in the second byte of the message and inbound messages should use the constant
+ * Map VAL_TO_CT during construction
+ */
+ private final OPCode _opCode;
+
+ /**
+ * Represents client type which there are currently 3 types supported.
+ * Uses the 3rd byte of the message and inbound messages should use the constant Map VAL_TO_OP during construction
+ */
+ private final ClientType _cType;
+
+ /**
+ * Easy constructor that implies version 1 and UNSOLICITED flag.
+ *
+ * User should leverage the main constructor below and set the version and flags.
+ *
+ * @param opCode - the Operation code denoting the type of message
+ * @param clientType - the client type generally denotes if it is an Ipv4 (TYPE_1) else Ipv6
+ * @throws java.lang.IllegalArgumentException
+ */
+ @Deprecated
+ public COPSHeader(final OPCode opCode, final ClientType clientType) {
+ this(1, Flag.UNSOLICITED, opCode, clientType);
+ }
+
+ /**
+ * Should be the main constructor.
+ * @param version - PCMM Version
+ * @param flag - the header flag
+ * @param opCode - the COPS operation code
+ * @param clientType - the type of client interfacing
+ * @throws java.lang.IllegalArgumentException
+ */
+ public COPSHeader(final int version, final Flag flag, final OPCode opCode, final ClientType clientType) {
+ if(version < 1) throw new IllegalArgumentException("Invalid version number - " + version);
+ if(flag == null) throw new IllegalArgumentException("Flag is null");
+ if(opCode == null) throw new IllegalArgumentException("OPCode is null");
+ if(clientType == null) throw new IllegalArgumentException("clientType is null");
+ _pcmmVersion = version;
+ _flag = flag;
+ _opCode = opCode;
+ _cType = clientType;
+
+ // TODO - Determine why this??? - remove until this makes some sense
+// if (opCode.equals(OPCode.KA)) _cType = ClientType.NA;
+// else _cType = clientType;
+ }
+
+ // Getters
+ public int getPcmmVersion() { return _pcmmVersion; }
+ public Flag getFlag() { return _flag; }
+
+ /**
+ * Get header length
+ * @return an int
+ */
+ public int getHdrLength() {
+ return 8;
+ }
+
+ /**
+ * Get Operation Code
+ * @return a byte
+ */
+ public OPCode getOpCode() {
+ return _opCode;
+ }
+
+ /**
+ * Get client-type
+ * @return a short
+ */
+ public ClientType getClientType() {
+ return _cType;
+ }
+
+ /**
+ * Writes object to given network socket in network byte order
+ * @param socket a Socket
+ * @throws IOException
+ */
+ public void writeData(final Socket socket, final int msgLength) throws IOException {
+ byte buf[] = new byte[8];
+ buf[0] = (byte) COPSMsgParser.combineNibbles((byte)_pcmmVersion, (byte) _flag.ordinal());
+ buf[1] = (byte) _opCode.ordinal();
+ buf[2] = (byte) (_cType.ordinal() >> 8);
+ buf[3] = (byte) _cType.ordinal();
+ buf[4] = (byte) (msgLength >> 24);
+ buf[5] = (byte) (msgLength >> 16);
+ buf[6] = (byte) (msgLength >> 8);
+ buf[7] = (byte) msgLength;
+ COPSUtil.writeData(socket, buf, 8);
+ }
+
+ @Override
+ public String toString() {
+ return "**MSG HEADER** \n"
+ + "Version: " + _pcmmVersion + "\n"
+ + "Flags: " + _flag + "\n"
+ + "OpCode: " + _opCode + "\n"
+ + "Client-type: " + _cType + "\n";
+ }
+
+ /**
+ * Write an object textual description in the output stream
+ * @param os an OutputStream
+ * @throws IOException
+ */
+ public void dump(OutputStream os) throws IOException {
+ os.write(("**MSG HEADER**" + "\n").getBytes());
+ os.write(("Version: " + _pcmmVersion + "\n").getBytes());
+ os.write(("Flags: " + _flag + "\n").getBytes());
+ os.write(("OpCode: " + _opCode + "\n").getBytes());
+ os.write(("Client-type: " + _cType + "\n").getBytes());
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof COPSHeader)) {
+ return false;
+ }
+
+ final COPSHeader header = (COPSHeader) o;
+
+ return _pcmmVersion == header._pcmmVersion && _cType == header._cType && _flag == header._flag &&
+ _opCode == header._opCode;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = _pcmmVersion;
+ result = 31 * result + _flag.hashCode();
+ result = 31 * result + _opCode.hashCode();
+ result = 31 * result + _cType.hashCode();
+ return result;
+ }
+
+ /**
+ * The types of COPS clients
+ *
+ * 0 = N/A - placeholder for the invalid value of 0
+ * 1 = TYPE_1 - Represents legacy endpoints (PC applications, game consoles) lacking QoS awareness or
+ * signaling capabilities.
+ * 2 = TYPE_2 - Represents a client that is similar to PacketCable 1.x telophony MTA which should support Qos
+ * signaling.
+ * 3 = TYPE_3 - Represents QoS treatment from the access network withouth Application Manager interaction
+ */
+ public enum ClientType {
+ NA, TYPE_1, TYPE_2, TYPE_3
+ }
+
+ /**
+ * Represents the COPS Operation code and byte value corresponds to the item's ordinal value
+ * The COPS operations:
+ * 0 = N/A - placeholder for the invalid value of 0
+ * 1 = Request (REQ)
+ * 2 = Decision (DEC)
+ * 3 = Report State (RPT)
+ * 4 = Delete Request State (DRQ)
+ * 5 = Synchronize State Req (SSQ)
+ * 6 = Client-Open (OPN)
+ * 7 = Client-Accept (CAT)
+ * 8 = Client-Close (CC)
+ * 9 = Keep-Alive (KA)
+ * 10= Synchronize Complete (SSC)
+ */
+ public enum OPCode {
+ NA, REQ, DEC, RPT, DRQ, SSQ, OPN, CAT, CC, KA, SSC
+ }
+
+ /**
+ * Represents the COPS flags value where the inbound nibble value maps to the ordinal values.
+ */
+ public enum Flag {
+ UNSOLICITED, SOLICITED
+ }
+
+}
+
+
+
+