Created a client-type enumeration as part of the original COPS refactor and have...
[packetcable.git] / packetcable-driver / src / main / java / org / umu / cops / stack / COPSHeader.java
1 /*
2  * Copyright (c) 2003 University of Murcia.  All rights reserved.
3  * --------------------------------------------------------------
4  * For more information, please see <http://www.umu.euro6ix.org/>.
5  */
6
7 package org.umu.cops.stack;
8
9 import java.io.IOException;
10 import java.io.OutputStream;
11 import java.net.Socket;
12 import java.util.Map;
13 import java.util.concurrent.ConcurrentHashMap;
14
15 /**
16  * COPS Header (RFC 2748 pag. 6)
17  *
18  *   Each COPS message consists of the COPS header followed by a number of
19  *   typed objects.
20  *
21  *             0              1              2              3
22  *     +--------------+--------------+--------------+--------------+
23  *     |Version| Flags|    Op Code   |       Client-type           |
24  *     +--------------+--------------+--------------+--------------+
25  *     |                      Message Length                       |
26  *     +--------------+--------------+--------------+--------------+
27  *
28  *     Global note: //// implies field is reserved, set to 0.
29  *
30  *       The fields in the header are:
31  *         Version: 4 bits
32  *             COPS version number. Current version is 1.
33  *
34  *         Flags: 4 bits
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.
40  *
41  *         Op Code: 8 bits
42  *            The COPS operations:
43  *              1 = Request                 (REQ)
44  *              2 = Decision                (DEC)
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)
51  *              9 = Keep-Alive              (KA)
52  *              10= Synchronize Complete    (SSC)
53  *
54  *       Client-type: 16 bits
55  *
56  *
57  * @version COPSHeader.java, v 1.00 2003
58  *
59  */
60 public class COPSHeader {
61
62     /**
63      * Map allowing for the quick retrieval of the operation based on the numeric value coming in via the
64      * COPS payload.
65      */
66     final static Map<Integer, OPCode> VAL_TO_OP = new ConcurrentHashMap<>();
67     static {
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);
79     }
80
81     /**
82      * Represents the PCMM version number of the message
83      * Holds the first nibble of the COPS message
84      */
85     private final int _pcmmVersion;
86
87     /**
88      * Represents the second nibble of the message where solicited decisions will be set to 1 else 0
89      * Values 0 = UNSOLICITED | 1 = SOLICITED
90      */
91     private final Flag _flag;
92
93     /**
94      * Represents the type of operation which will be used to determine the type of COPSMsg this header will be a
95      * part of.
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
98      */
99     private final OPCode _opCode;
100
101     /**
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
104      */
105     private final short _cType;
106
107     /**
108      * Easy constructor that implies version 1 and UNSOLICITED flag.
109      *
110      * User should leverage the main constructor below and set the version and flags.
111      *
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
115      */
116     @Deprecated
117     public COPSHeader(final OPCode opCode, final short clientType) {
118         this(1, Flag.UNSOLICITED, opCode, clientType);
119     }
120
121     /**
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
128      */
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;
134         _flag = flag;
135         _opCode = opCode;
136         _cType = clientType;
137
138         // TODO - Determine why this??? - remove until this makes some sense
139 //        if (opCode.equals(OPCode.KA)) _cType = ClientType.NA;
140 //        else _cType = clientType;
141     }
142
143     // Getters
144     public int getPcmmVersion() { return _pcmmVersion; }
145     public Flag getFlag() { return _flag; }
146
147     /**
148      * Get header length
149      * @return   an int
150      */
151     public int getHdrLength() {
152         return 8;
153     }
154
155     /**
156      * Get Operation Code
157      * @return   a byte
158      */
159     public OPCode getOpCode() {
160         return _opCode;
161     }
162
163     /**
164      * Get client-type
165      * @return   a short
166      */
167     public short getClientType() {
168         return _cType;
169     }
170
171     /**
172      * Writes object to given network socket in network byte order
173      * @param    socket                  a  Socket
174      * @throws   IOException
175      */
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();
180
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);
189     }
190
191     @Override
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";
198     }
199
200     /**
201      * Write an object textual description in the output stream
202      * @param    os                  an OutputStream
203      * @throws   IOException
204      */
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());
211     }
212
213     @Override
214     public boolean equals(final Object o) {
215         if (this == o) {
216             return true;
217         }
218         if (!(o instanceof COPSHeader)) {
219             return false;
220         }
221
222         final COPSHeader header = (COPSHeader) o;
223
224         return _pcmmVersion == header._pcmmVersion && _cType == header._cType && _flag == header._flag &&
225                 _opCode == header._opCode;
226
227     }
228
229     @Override
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;
235         return result;
236     }
237
238     /**
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
242      *              1 = Request                 (REQ)
243      *              2 = Decision                (DEC)
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)
252      */
253     public enum OPCode {
254         NA, REQ, DEC, RPT, DRQ, SSQ, OPN, CAT, CC, KA, SSC
255     }
256
257     /**
258      * Represents the COPS flags value where the inbound nibble value maps to the ordinal values.
259      */
260     public enum Flag {
261         UNSOLICITED, SOLICITED
262     }
263
264 }
265
266
267
268