blob: 4e9bc127a13631bf285348b69234195df2de76e2 [file] [log] [blame]
slowr60d4d102017-08-16 18:33:58 -07001/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Dimitrios Mavrommatis96b255a2017-12-06 13:09:25 -08004package org.onosproject.xran.asn1lib.ber;
slowr60d4d102017-08-16 18:33:58 -07005
6import java.io.EOFException;
7import java.io.IOException;
8import java.io.InputStream;
9import java.io.Serializable;
10
11public class BerTag implements Serializable {
12
13 public static final int UNIVERSAL_CLASS = 0x00;
14 public static final int APPLICATION_CLASS = 0x40;
15 public static final int CONTEXT_CLASS = 0x80;
16 public static final int PRIVATE_CLASS = 0xc0;
17 public static final int PRIMITIVE = 0x00;
18 public static final int CONSTRUCTED = 0x20;
19 public static final int BOOLEAN_TAG = 1;
20 public static final int INTEGER_TAG = 2;
21 public static final int BIT_STRING_TAG = 3;
22 public static final int OCTET_STRING_TAG = 4;
23 public static final int NULL_TAG = 5;
24 public static final int OBJECT_IDENTIFIER_TAG = 6;
25 public static final int OBJECT_DESCRIPTOR_TAG = 7;
26 public static final int REAL_TAG = 9;
27 public static final int ENUMERATED_TAG = 10;
28 public static final int EMBEDDED_PDV_TAG = 11;
29 public static final int UTF8_STRING_TAG = 12;
30 public static final int TIME_TAG = 14;
31 public static final int NUMERIC_STRING_TAG = 18;
32 public static final int PRINTABLE_STRING_TAG = 19;
33 public static final int TELETEX_STRING_TAG = 20;
34 public static final int VIDEOTEX_STRING_TAG = 21;
35 public static final int IA5_STRING_TAG = 22;
36 public static final int UTC_TIME_TAG = 23;
37 public static final int GENERALIZED_TIME_TAG = 24;
38 public static final int GRAPHIC_STRING_TAG = 25;
39 public static final int VISIBLE_STRING_TAG = 26;
40 public static final int GENERAL_STRING_TAG = 27;
41 public static final int UNIVERSAL_STRING_TAG = 28;
42 public static final int BMP_STRING_TAG = 30;
43 public static final int DATE_TAG = 31;
44 public static final int TIME_OF_DAY_TAG = 32;
45 public static final int DATE_TIME_TAG = 33;
46 public static final int DURATION_TAG = 34;
47 private static final long serialVersionUID = 1L;
48 public byte[] tagBytes = null;
49 public int tagClass;
50 public int primitive;
51 public int tagNumber;
52
53 public BerTag(int identifierClass, int primitive, int tagNumber) {
54 this.tagClass = identifierClass;
55 this.primitive = primitive;
56 this.tagNumber = tagNumber;
57 code();
58 }
59
60 public BerTag() {
61 }
62
63 private void code() {
64 if (tagNumber < 31) {
65 tagBytes = new byte[1];
66 tagBytes[0] = (byte) (tagClass | primitive | tagNumber);
67 } else {
68 int tagLength = 1;
69 while (tagNumber > (Math.pow(2, (7 * tagLength)) - 1)) {
70 tagLength++;
71 }
72
73 tagBytes = new byte[1 + tagLength];
74 tagBytes[0] = (byte) (tagClass | primitive | 31);
75
76 for (int j = 1; j <= (tagLength - 1); j++) {
77 tagBytes[j] = (byte) (((tagNumber >> (7 * (tagLength - j))) & 0xff) | 0x80);
78 }
79
80 tagBytes[tagLength] = (byte) (tagNumber & 0x7f);
81
82 }
83 }
84
85 public int encode(BerByteArrayOutputStream os) throws IOException {
86 if (tagBytes == null) {
87 code();
88 }
89 for (int i = (tagBytes.length - 1); i >= 0; i--) {
90 os.write(tagBytes[i]);
91 }
92 return tagBytes.length;
93 }
94
95 public int decode(InputStream is) throws IOException {
96 int nextByte = is.read();
97 if (nextByte == -1) {
98 throw new EOFException("Unexpected end of input stream.");
99 }
100
101 tagClass = nextByte & 0xC0;
102 primitive = nextByte & 0x20;
103 tagNumber = nextByte & 0x1f;
104
105 int codeLength = 1;
106
107 if (tagNumber == 0x1f) {
108 tagNumber = 0;
109
110 int counter = 0;
111
112 do {
113 nextByte = is.read();
114 if (nextByte == -1) {
115 throw new EOFException("Unexpected end of input stream.");
116 }
117
118 codeLength++;
119 if (counter >= 6) {
120 throw new IOException("Invalid Tag");
121 }
122 tagNumber = tagNumber << 7;
123 tagNumber |= (nextByte & 0x7f);
124 counter++;
125 } while ((nextByte & 0x80) == 0x80);
126
127 }
128
129 return codeLength;
130 }
131
132 /**
133 * Decodes the Identifier from the ByteArrayInputStream and throws an Exception if it is not equal to itself.
134 * Returns the number of bytes read from the InputStream.
135 *
136 * @param is the input stream to read the identifier from.
137 * @return the length of the identifier read.
138 * @throws IOException if an exception occurs reading the identifier from the stream.
139 */
140 public int decodeAndCheck(InputStream is) throws IOException {
141
142 for (Byte identifierByte : tagBytes) {
143 int nextByte = is.read();
144 if (nextByte == -1) {
145 throw new EOFException("Unexpected end of input stream.");
146 }
147
148 if (nextByte != (identifierByte & 0xff)) {
149 throw new IOException("Identifier does not match!");
150 }
151 }
152 return tagBytes.length;
153 }
154
155 public boolean equals(int identifierClass, int primitive, int tagNumber) {
156 return (this.tagNumber == tagNumber && this.tagClass == identifierClass && this.primitive == primitive);
157 }
158
159 @Override
160 public boolean equals(Object obj) {
161 if (!(obj instanceof BerTag)) {
162 return false;
163 }
164 if (obj == this) {
165 return true;
166 }
167 BerTag berIdentifier = (BerTag) obj;
168 return (tagNumber == berIdentifier.tagNumber && tagClass == berIdentifier.tagClass
169 && primitive == berIdentifier.primitive);
170 }
171
172 @Override
173 public int hashCode() {
174 int hash = 17;
175 hash = hash * 31 + tagNumber;
176 hash = hash * 31 + tagClass;
177 hash = hash * 31 + primitive;
178 return hash;
179 }
180
181 @Override
182 public String toString() {
183 return "identifier class: " + tagClass + ", primitive: " + primitive + ", tag number: " + tagNumber;
184 }
185
186}