blob: 14399c250482945975986a82a884cd683c3830c6 [file] [log] [blame]
Jian Li451175e2016-07-19 23:22:20 +09001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.lisp.msg.protocols;
17
Jian Li20850d32016-08-04 02:15:57 +090018import com.google.common.base.Objects;
Jian Lif59c0ad2016-08-02 18:11:30 +090019import com.google.common.collect.ImmutableList;
20import com.google.common.collect.Lists;
Jian Li451175e2016-07-19 23:22:20 +090021import io.netty.buffer.ByteBuf;
Jian Lif59c0ad2016-08-02 18:11:30 +090022import org.onlab.util.ImmutableByteSequence;
Jian Li26069e22016-08-10 22:00:52 +090023import org.onosproject.lisp.msg.exceptions.LispParseError;
Jian Lia7b394d2016-08-21 23:11:46 +090024import org.onosproject.lisp.msg.exceptions.LispReaderException;
Jian Liedc5db12016-08-23 17:30:19 +090025import org.onosproject.lisp.msg.exceptions.LispWriterException;
Jian Li451175e2016-07-19 23:22:20 +090026
Jian Liedc5db12016-08-23 17:30:19 +090027import java.util.Arrays;
Jian Li719b3bf2016-07-22 00:38:29 +090028import java.util.List;
29
Jian Li20850d32016-08-04 02:15:57 +090030import static com.google.common.base.MoreObjects.toStringHelper;
Jian Liedc5db12016-08-23 17:30:19 +090031import static org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.MapRecordWriter;
Jian Li20850d32016-08-04 02:15:57 +090032
Jian Li451175e2016-07-19 23:22:20 +090033/**
34 * Default LISP map notify message class.
35 */
Jian Lif59c0ad2016-08-02 18:11:30 +090036public final class DefaultLispMapNotify implements LispMapNotify {
37
38 private final long nonce;
39 private final short keyId;
Jian Liedc5db12016-08-23 17:30:19 +090040 private final short authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +090041 private final byte[] authenticationData;
42 private final byte recordCount;
43 private final List<LispMapRecord> mapRecords;
44
45 /**
46 * A private constructor that protects object instantiation from external.
47 *
48 * @param nonce nonce
49 * @param keyId key identifier
50 * @param authenticationData authentication data
51 * @param recordCount record count number
52 * @param mapRecords a collection of map records
53 */
Jian Liedc5db12016-08-23 17:30:19 +090054 private DefaultLispMapNotify(long nonce, short keyId, short authDataLength,
55 byte[] authenticationData, byte recordCount,
56 List<LispMapRecord> mapRecords) {
Jian Lif59c0ad2016-08-02 18:11:30 +090057 this.nonce = nonce;
58 this.keyId = keyId;
Jian Liedc5db12016-08-23 17:30:19 +090059 this.authDataLength = authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +090060 this.authenticationData = authenticationData;
61 this.recordCount = recordCount;
62 this.mapRecords = mapRecords;
63 }
Jian Li451175e2016-07-19 23:22:20 +090064
65 @Override
66 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090067 return LispType.LISP_MAP_NOTIFY;
Jian Li451175e2016-07-19 23:22:20 +090068 }
69
70 @Override
71 public void writeTo(ByteBuf byteBuf) {
Jian Lif59c0ad2016-08-02 18:11:30 +090072 // TODO: serialize LispMapRegister message
Jian Li451175e2016-07-19 23:22:20 +090073 }
74
75 @Override
76 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090077 return new DefaultNotifyBuilder();
Jian Li451175e2016-07-19 23:22:20 +090078 }
Jian Li719b3bf2016-07-22 00:38:29 +090079
80 @Override
81 public long getNonce() {
Jian Liedc5db12016-08-23 17:30:19 +090082 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +090083 }
84
85 @Override
86 public byte getRecordCount() {
Jian Liedc5db12016-08-23 17:30:19 +090087 return recordCount;
Jian Li719b3bf2016-07-22 00:38:29 +090088 }
89
90 @Override
91 public short getKeyId() {
Jian Liedc5db12016-08-23 17:30:19 +090092 return keyId;
93 }
94
95 @Override
96 public short getAuthDataLength() {
97 return authDataLength;
Jian Li719b3bf2016-07-22 00:38:29 +090098 }
99
100 @Override
101 public byte[] getAuthenticationData() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900102 if (authenticationData != null && authenticationData.length != 0) {
103 return ImmutableByteSequence.copyFrom(authenticationData).asArray();
104 } else {
105 return new byte[0];
106 }
Jian Li719b3bf2016-07-22 00:38:29 +0900107 }
108
109 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900110 public List<LispMapRecord> getMapRecords() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900111 return ImmutableList.copyOf(mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900112 }
113
Jian Li20850d32016-08-04 02:15:57 +0900114 @Override
115 public String toString() {
116 return toStringHelper(this)
117 .add("type", getType())
118 .add("nonce", nonce)
119 .add("recordCount", recordCount)
120 .add("keyId", keyId)
Jian Liedc5db12016-08-23 17:30:19 +0900121 .add("authentication data length", authDataLength)
122 .add("authentication data", authenticationData)
Jian Li20850d32016-08-04 02:15:57 +0900123 .add("mapRecords", mapRecords).toString();
124 }
125
126 @Override
127 public boolean equals(Object o) {
128 if (this == o) {
129 return true;
130 }
131 if (o == null || getClass() != o.getClass()) {
132 return false;
133 }
134 DefaultLispMapNotify that = (DefaultLispMapNotify) o;
135 return Objects.equal(nonce, that.nonce) &&
136 Objects.equal(recordCount, that.recordCount) &&
137 Objects.equal(keyId, that.keyId) &&
Jian Liedc5db12016-08-23 17:30:19 +0900138 Objects.equal(authDataLength, that.authDataLength) &&
Jian Lie4ba2a42016-08-29 20:24:15 +0900139 Arrays.equals(authenticationData, that.authenticationData);
Jian Li20850d32016-08-04 02:15:57 +0900140 }
141
142 @Override
143 public int hashCode() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900144 return Objects.hashCode(nonce, recordCount, keyId, authDataLength) +
145 Arrays.hashCode(authenticationData);
Jian Li20850d32016-08-04 02:15:57 +0900146 }
147
Jian Li719b3bf2016-07-22 00:38:29 +0900148 public static final class DefaultNotifyBuilder implements NotifyBuilder {
149
Jian Lif59c0ad2016-08-02 18:11:30 +0900150 private long nonce;
151 private short keyId;
Jian Liedc5db12016-08-23 17:30:19 +0900152 private short authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +0900153 private byte[] authenticationData;
154 private byte recordCount;
Jian Li47671902016-08-11 01:18:18 +0900155 private List<LispMapRecord> mapRecords;
Jian Li719b3bf2016-07-22 00:38:29 +0900156
157 @Override
158 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900159 return LispType.LISP_MAP_NOTIFY;
Jian Li719b3bf2016-07-22 00:38:29 +0900160 }
161
162 @Override
163 public NotifyBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900164 this.nonce = nonce;
165 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900166 }
167
168 @Override
169 public NotifyBuilder withRecordCount(byte recordCount) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900170 this.recordCount = recordCount;
171 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900172 }
173
174 @Override
175 public NotifyBuilder withKeyId(short keyId) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900176 this.keyId = keyId;
177 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900178 }
179
180 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900181 public NotifyBuilder withAuthDataLength(short authDataLength) {
182 this.authDataLength = authDataLength;
183 return this;
184 }
185
186 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900187 public NotifyBuilder withAuthenticationData(byte[] authenticationData) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900188 if (authenticationData != null) {
189 this.authenticationData = authenticationData;
190 } else {
191 this.authenticationData = new byte[0];
192 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900193 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900194 }
195
196 @Override
Jian Li47671902016-08-11 01:18:18 +0900197 public NotifyBuilder withMapRecords(List<LispMapRecord> mapRecords) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900198 if (mapRecords != null) {
199 this.mapRecords = ImmutableList.copyOf(mapRecords);
200 } else {
201 this.mapRecords = Lists.newArrayList();
202 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900203 return this;
204 }
205
206 @Override
Jian Li525fded2016-08-04 01:15:33 +0900207 public LispMapNotify build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900208
209 if (authenticationData == null) {
210 authenticationData = new byte[0];
211 }
212
213 if (mapRecords == null) {
214 mapRecords = Lists.newArrayList();
215 }
216
Jian Liedc5db12016-08-23 17:30:19 +0900217 return new DefaultLispMapNotify(nonce, keyId, authDataLength,
218 authenticationData, recordCount, mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900219 }
220 }
Jian Li26069e22016-08-10 22:00:52 +0900221
222 /**
Jian Liedc5db12016-08-23 17:30:19 +0900223 * A LISP message reader for MapNotify message.
Jian Li26069e22016-08-10 22:00:52 +0900224 */
Jian Liedc5db12016-08-23 17:30:19 +0900225 public static final class NotifyReader implements LispMessageReader<LispMapNotify> {
Jian Li26069e22016-08-10 22:00:52 +0900226
Jian Li47671902016-08-11 01:18:18 +0900227 private static final int RESERVED_SKIP_LENGTH = 3;
228
Jian Li26069e22016-08-10 22:00:52 +0900229 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900230 public LispMapNotify readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900231
232 if (byteBuf.readerIndex() != 0) {
233 return null;
234 }
235
236 // skip first three bytes as they represent type and reserved fields
237 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
238
239 // record count -> 8 bits
240 byte recordCount = (byte) byteBuf.readUnsignedByte();
241
242 // nonce -> 64 bits
243 long nonce = byteBuf.readLong();
244
245 // keyId -> 16 bits
246 short keyId = byteBuf.readShort();
247
248 // authenticationDataLength -> 16 bits
249 short authLength = byteBuf.readShort();
250
251 // authenticationData -> depends on the authenticationDataLength
252 byte[] authData = new byte[authLength];
253 byteBuf.readBytes(authData);
254
255 List<LispMapRecord> mapRecords = Lists.newArrayList();
256 for (int i = 0; i < recordCount; i++) {
257 mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
258 }
259
260 return new DefaultNotifyBuilder()
261 .withRecordCount(recordCount)
262 .withNonce(nonce)
263 .withKeyId(keyId)
Jian Liedc5db12016-08-23 17:30:19 +0900264 .withAuthDataLength(authLength)
Jian Li47671902016-08-11 01:18:18 +0900265 .withAuthenticationData(authData)
266 .withMapRecords(mapRecords)
267 .build();
Jian Li26069e22016-08-10 22:00:52 +0900268 }
269 }
Jian Liedc5db12016-08-23 17:30:19 +0900270
271 /**
272 * A LISP message reader for MapNotify message.
273 */
274 public static final class NotifyWriter implements LispMessageWriter<LispMapNotify> {
275
276 private static final int NOTIFY_MSG_TYPE = 4;
277 private static final int NOTIFY_SHIFT_BIT = 4;
278
279 private static final int UNUSED_ZERO = 0;
280
281 @Override
282 public void writeTo(ByteBuf byteBuf, LispMapNotify message) throws LispWriterException {
283
284 // specify LISP message type
285 byte msgType = (byte) (NOTIFY_MSG_TYPE << NOTIFY_SHIFT_BIT);
286 byteBuf.writeByte(msgType);
287
288 // reserved field
289 byteBuf.writeShort((short) UNUSED_ZERO);
290
291 // record count
292 byteBuf.writeByte(message.getRecordCount());
293
294 // nonce
295 byteBuf.writeLong(message.getNonce());
296
297 // keyId
298 byteBuf.writeShort(message.getKeyId());
299
300 // authentication data length in octet
301 byteBuf.writeShort(message.getAuthDataLength());
302
303 // authentication data
304 byte[] data = message.getAuthenticationData();
305 byte[] clone;
306 if (data != null) {
307 clone = data.clone();
308 Arrays.fill(clone, (byte) UNUSED_ZERO);
309 }
310
311 byteBuf.writeBytes(data);
312
313 // TODO: need to implement MAC authentication mechanism
314
315 // serialize map records
316 MapRecordWriter writer = new MapRecordWriter();
317 List<LispMapRecord> records = message.getMapRecords();
318
319 for (int i = 0; i < records.size(); i++) {
320 writer.writeTo(byteBuf, records.get(i));
321 }
322 }
323 }
Jian Li451175e2016-07-19 23:22:20 +0900324}