2 * Copyright (c) 2003 University of Murcia. All rights reserved.
3 * --------------------------------------------------------------
4 * For more information, please see <http://www.umu.euro6ix.org/>.
7 package org.umu.cops.stack;
9 import java.io.IOException;
10 import java.io.OutputStream;
11 import java.net.Socket;
13 import java.util.concurrent.ConcurrentHashMap;
16 * COPS Header (RFC 2748 pag. 6)
18 * Each COPS message consists of the COPS header followed by a number of
22 * +--------------+--------------+--------------+--------------+
23 * |Version| Flags| Op Code | Client-type |
24 * +--------------+--------------+--------------+--------------+
26 * +--------------+--------------+--------------+--------------+
28 * Global note: //// implies field is reserved, set to 0.
30 * The fields in the header are:
32 * COPS version number. Current version is 1.
35 * Defined flag values (all other flags MUST be set to 0):
36 * 0x1 Solicited Message Flag Bit
37 * This flag is set when the message is solicited by
38 * another COPS message. This flag is NOT to be set
39 * (value=0) unless otherwise specified.
42 * The COPS operations:
45 * 3 = Report State (RPT)
46 * 4 = Delete Request State (DRQ)
47 * 5 = Synchronize State Req (SSQ)
48 * 6 = Client-Open (OPN)
49 * 7 = Client-Accept (CAT)
50 * 8 = Client-Close (CC)
52 * 10= Synchronize Complete (SSC)
54 * Client-type: 16 bits
57 * @version COPSHeader.java, v 1.00 2003
60 public class COPSHeader {
63 * Map allowing for the quick retrieval of the operation based on the numeric value coming in via the
66 final static Map<Integer, OPCode> VAL_TO_OP = new ConcurrentHashMap<>();
68 VAL_TO_OP.put(OPCode.NA.ordinal(), OPCode.NA);
69 VAL_TO_OP.put(OPCode.REQ.ordinal(), OPCode.REQ);
70 VAL_TO_OP.put(OPCode.DEC.ordinal(), OPCode.DEC);
71 VAL_TO_OP.put(OPCode.RPT.ordinal(), OPCode.RPT);
72 VAL_TO_OP.put(OPCode.DRQ.ordinal(), OPCode.DRQ);
73 VAL_TO_OP.put(OPCode.SSQ.ordinal(), OPCode.SSQ);
74 VAL_TO_OP.put(OPCode.OPN.ordinal(), OPCode.OPN);
75 VAL_TO_OP.put(OPCode.CAT.ordinal(), OPCode.CAT);
76 VAL_TO_OP.put(OPCode.CC.ordinal(), OPCode.CC);
77 VAL_TO_OP.put(OPCode.KA.ordinal(), OPCode.KA);
78 VAL_TO_OP.put(OPCode.SSC.ordinal(), OPCode.SSC);
82 * Represents the PCMM version number of the message
83 * Holds the first nibble of the COPS message
85 private final int _pcmmVersion;
88 * Represents the second nibble of the message where solicited decisions will be set to 1 else 0
89 * Values 0 = UNSOLICITED | 1 = SOLICITED
91 private final Flag _flag;
94 * Represents the type of operation which will be used to determine the type of COPSMsg this header will be a
96 * Uses the byte value contained in the second byte of the message and inbound messages should use the constant
97 * Map VAL_TO_CT during construction
99 private final OPCode _opCode;
102 * Represents client type which there are currently 3 types supported.
103 * Uses the 3rd byte of the message and inbound messages should use the constant Map VAL_TO_OP during construction
105 private final short _cType;
108 * Easy constructor that implies version 1 and UNSOLICITED flag.
110 * User should leverage the main constructor below and set the version and flags.
112 * @param opCode - the Operation code denoting the type of message
113 * @param clientType - the client type generally denotes if it is an Ipv4 (TYPE_1) else Ipv6
114 * @throws java.lang.IllegalArgumentException
117 public COPSHeader(final OPCode opCode, final short clientType) {
118 this(1, Flag.UNSOLICITED, opCode, clientType);
122 * Should be the main constructor.
123 * @param version - PCMM Version
124 * @param flag - the header flag
125 * @param opCode - the COPS operation code
126 * @param clientType - the type of client interfacing
127 * @throws java.lang.IllegalArgumentException
129 public COPSHeader(final int version, final Flag flag, final OPCode opCode, final short clientType) {
130 if(version < 1) throw new IllegalArgumentException("Invalid version number - " + version);
131 if(flag == null) throw new IllegalArgumentException("Flag is null");
132 if(opCode == null) throw new IllegalArgumentException("OPCode is null");
133 _pcmmVersion = version;
138 // TODO - Determine why this??? - remove until this makes some sense
139 // if (opCode.equals(OPCode.KA)) _cType = ClientType.NA;
140 // else _cType = clientType;
144 public int getPcmmVersion() { return _pcmmVersion; }
145 public Flag getFlag() { return _flag; }
151 public int getHdrLength() {
159 public OPCode getOpCode() {
167 public short getClientType() {
172 * Writes object to given network socket in network byte order
173 * @param socket a Socket
174 * @throws IOException
176 public void writeData(final Socket socket, final int msgLength) throws IOException {
177 byte buf[] = new byte[8];
178 buf[0] = (byte) COPSMsgParser.combineNibbles((byte)_pcmmVersion, (byte) _flag.ordinal());
179 buf[1] = (byte) _opCode.ordinal();
181 final byte[] cTypeBytes = COPSMsgParser.shortToBytes(_cType);
182 buf[2] = cTypeBytes[0];
183 buf[3] = cTypeBytes[1];
184 buf[4] = (byte) (msgLength >> 24);
185 buf[5] = (byte) (msgLength >> 16);
186 buf[6] = (byte) (msgLength >> 8);
187 buf[7] = (byte) msgLength;
188 COPSUtil.writeData(socket, buf, 8);
192 public String toString() {
193 return "**MSG HEADER** \n"
194 + "Version: " + _pcmmVersion + "\n"
195 + "Flags: " + _flag + "\n"
196 + "OpCode: " + _opCode + "\n"
197 + "Client-type: " + _cType + "\n";
201 * Write an object textual description in the output stream
202 * @param os an OutputStream
203 * @throws IOException
205 public void dump(OutputStream os) throws IOException {
206 os.write(("**MSG HEADER**" + "\n").getBytes());
207 os.write(("Version: " + _pcmmVersion + "\n").getBytes());
208 os.write(("Flags: " + _flag + "\n").getBytes());
209 os.write(("OpCode: " + _opCode + "\n").getBytes());
210 os.write(("Client-type: " + _cType + "\n").getBytes());
214 public boolean equals(final Object o) {
218 if (!(o instanceof COPSHeader)) {
222 final COPSHeader header = (COPSHeader) o;
224 return _pcmmVersion == header._pcmmVersion && _cType == header._cType && _flag == header._flag &&
225 _opCode == header._opCode;
230 public int hashCode() {
231 int result = _pcmmVersion;
232 result = 31 * result + _flag.hashCode();
233 result = 31 * result + _opCode.hashCode();
234 result = 31 * result + _cType;
239 * Represents the COPS Operation code and byte value corresponds to the item's ordinal value
240 * The COPS operations:
241 * 0 = N/A - placeholder for the invalid value of 0
244 * 3 = Report State (RPT)
245 * 4 = Delete Request State (DRQ)
246 * 5 = Synchronize State Req (SSQ)
247 * 6 = Client-Open (OPN)
248 * 7 = Client-Accept (CAT)
249 * 8 = Client-Close (CC)
250 * 9 = Keep-Alive (KA)
251 * 10= Synchronize Complete (SSC)
254 NA, REQ, DEC, RPT, DRQ, SSQ, OPN, CAT, CC, KA, SSC
258 * Represents the COPS flags value where the inbound nibble value maps to the ordinal values.
261 UNSOLICITED, SOLICITED