blob: cb18b8ffe8ad2d9bc80800e234edac686b04b29e [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;
Jian Lif59c0ad2016-08-02 18:11:30 +090042 private final List<LispMapRecord> mapRecords;
43
Yoonseon Hanca814bf2016-09-12 11:37:48 -070044 static final NotifyWriter WRITER;
45 static {
46 WRITER = new NotifyWriter();
47 }
48
Jian Lif59c0ad2016-08-02 18:11:30 +090049 /**
50 * A private constructor that protects object instantiation from external.
51 *
52 * @param nonce nonce
53 * @param keyId key identifier
54 * @param authenticationData authentication data
Jian Lif59c0ad2016-08-02 18:11:30 +090055 * @param mapRecords a collection of map records
56 */
Jian Liedc5db12016-08-23 17:30:19 +090057 private DefaultLispMapNotify(long nonce, short keyId, short authDataLength,
Jian Li42b3e432016-08-31 01:05:20 +090058 byte[] authenticationData, List<LispMapRecord> mapRecords) {
Jian Lif59c0ad2016-08-02 18:11:30 +090059 this.nonce = nonce;
60 this.keyId = keyId;
Jian Liedc5db12016-08-23 17:30:19 +090061 this.authDataLength = authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +090062 this.authenticationData = authenticationData;
Jian Lif59c0ad2016-08-02 18:11:30 +090063 this.mapRecords = mapRecords;
64 }
Jian Li451175e2016-07-19 23:22:20 +090065
66 @Override
67 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090068 return LispType.LISP_MAP_NOTIFY;
Jian Li451175e2016-07-19 23:22:20 +090069 }
70
71 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -070072 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
73 WRITER.writeTo(byteBuf, this);
Jian Li451175e2016-07-19 23:22:20 +090074 }
75
76 @Override
77 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +090078 return new DefaultNotifyBuilder();
Jian Li451175e2016-07-19 23:22:20 +090079 }
Jian Li719b3bf2016-07-22 00:38:29 +090080
81 @Override
82 public long getNonce() {
Jian Liedc5db12016-08-23 17:30:19 +090083 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +090084 }
85
86 @Override
Jian Li42b3e432016-08-31 01:05:20 +090087 public int getRecordCount() {
88 return mapRecords.size();
Jian Li719b3bf2016-07-22 00:38:29 +090089 }
90
91 @Override
92 public short getKeyId() {
Jian Liedc5db12016-08-23 17:30:19 +090093 return keyId;
94 }
95
96 @Override
97 public short getAuthDataLength() {
98 return authDataLength;
Jian Li719b3bf2016-07-22 00:38:29 +090099 }
100
101 @Override
102 public byte[] getAuthenticationData() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900103 if (authenticationData != null && authenticationData.length != 0) {
104 return ImmutableByteSequence.copyFrom(authenticationData).asArray();
105 } else {
106 return new byte[0];
107 }
Jian Li719b3bf2016-07-22 00:38:29 +0900108 }
109
110 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900111 public List<LispMapRecord> getMapRecords() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900112 return ImmutableList.copyOf(mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900113 }
114
Jian Li20850d32016-08-04 02:15:57 +0900115 @Override
116 public String toString() {
117 return toStringHelper(this)
118 .add("type", getType())
119 .add("nonce", nonce)
Jian Li20850d32016-08-04 02:15:57 +0900120 .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) &&
Jian Li20850d32016-08-04 02:15:57 +0900136 Objects.equal(keyId, that.keyId) &&
Jian Liedc5db12016-08-23 17:30:19 +0900137 Objects.equal(authDataLength, that.authDataLength) &&
Jian Lie4ba2a42016-08-29 20:24:15 +0900138 Arrays.equals(authenticationData, that.authenticationData);
Jian Li20850d32016-08-04 02:15:57 +0900139 }
140
141 @Override
142 public int hashCode() {
Jian Li42b3e432016-08-31 01:05:20 +0900143 return Objects.hashCode(nonce, keyId, authDataLength) +
Jian Lie4ba2a42016-08-29 20:24:15 +0900144 Arrays.hashCode(authenticationData);
Jian Li20850d32016-08-04 02:15:57 +0900145 }
146
Jian Li719b3bf2016-07-22 00:38:29 +0900147 public static final class DefaultNotifyBuilder implements NotifyBuilder {
148
Jian Lif59c0ad2016-08-02 18:11:30 +0900149 private long nonce;
150 private short keyId;
Jian Liedc5db12016-08-23 17:30:19 +0900151 private short authDataLength;
Jian Lif59c0ad2016-08-02 18:11:30 +0900152 private byte[] authenticationData;
Jian Lid4e63702016-08-30 18:29:20 +0900153 private List<LispMapRecord> mapRecords = Lists.newArrayList();
Jian Li719b3bf2016-07-22 00:38:29 +0900154
155 @Override
156 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900157 return LispType.LISP_MAP_NOTIFY;
Jian Li719b3bf2016-07-22 00:38:29 +0900158 }
159
160 @Override
161 public NotifyBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900162 this.nonce = nonce;
163 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900164 }
165
166 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900167 public NotifyBuilder withKeyId(short keyId) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900168 this.keyId = keyId;
169 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900170 }
171
172 @Override
Jian Liedc5db12016-08-23 17:30:19 +0900173 public NotifyBuilder withAuthDataLength(short authDataLength) {
174 this.authDataLength = authDataLength;
175 return this;
176 }
177
178 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900179 public NotifyBuilder withAuthenticationData(byte[] authenticationData) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900180 if (authenticationData != null) {
181 this.authenticationData = authenticationData;
182 } else {
183 this.authenticationData = new byte[0];
184 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900185 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900186 }
187
188 @Override
Jian Li47671902016-08-11 01:18:18 +0900189 public NotifyBuilder withMapRecords(List<LispMapRecord> mapRecords) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900190 if (mapRecords != null) {
191 this.mapRecords = ImmutableList.copyOf(mapRecords);
Jian Lie4ba2a42016-08-29 20:24:15 +0900192 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900193 return this;
194 }
195
196 @Override
Jian Li525fded2016-08-04 01:15:33 +0900197 public LispMapNotify build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900198
199 if (authenticationData == null) {
200 authenticationData = new byte[0];
201 }
202
Jian Liedc5db12016-08-23 17:30:19 +0900203 return new DefaultLispMapNotify(nonce, keyId, authDataLength,
Jian Li42b3e432016-08-31 01:05:20 +0900204 authenticationData, mapRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900205 }
206 }
Jian Li26069e22016-08-10 22:00:52 +0900207
208 /**
Jian Liedc5db12016-08-23 17:30:19 +0900209 * A LISP message reader for MapNotify message.
Jian Li26069e22016-08-10 22:00:52 +0900210 */
Jian Liedc5db12016-08-23 17:30:19 +0900211 public static final class NotifyReader implements LispMessageReader<LispMapNotify> {
Jian Li26069e22016-08-10 22:00:52 +0900212
Jian Li47671902016-08-11 01:18:18 +0900213 private static final int RESERVED_SKIP_LENGTH = 3;
214
Jian Li26069e22016-08-10 22:00:52 +0900215 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900216 public LispMapNotify readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900217
218 if (byteBuf.readerIndex() != 0) {
219 return null;
220 }
221
222 // skip first three bytes as they represent type and reserved fields
223 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
224
225 // record count -> 8 bits
226 byte recordCount = (byte) byteBuf.readUnsignedByte();
227
228 // nonce -> 64 bits
229 long nonce = byteBuf.readLong();
230
231 // keyId -> 16 bits
232 short keyId = byteBuf.readShort();
233
234 // authenticationDataLength -> 16 bits
235 short authLength = byteBuf.readShort();
236
237 // authenticationData -> depends on the authenticationDataLength
238 byte[] authData = new byte[authLength];
239 byteBuf.readBytes(authData);
240
241 List<LispMapRecord> mapRecords = Lists.newArrayList();
242 for (int i = 0; i < recordCount; i++) {
243 mapRecords.add(new DefaultLispMapRecord.MapRecordReader().readFrom(byteBuf));
244 }
245
246 return new DefaultNotifyBuilder()
Jian Li47671902016-08-11 01:18:18 +0900247 .withNonce(nonce)
248 .withKeyId(keyId)
Jian Liedc5db12016-08-23 17:30:19 +0900249 .withAuthDataLength(authLength)
Jian Li47671902016-08-11 01:18:18 +0900250 .withAuthenticationData(authData)
251 .withMapRecords(mapRecords)
252 .build();
Jian Li26069e22016-08-10 22:00:52 +0900253 }
254 }
Jian Liedc5db12016-08-23 17:30:19 +0900255
256 /**
257 * A LISP message reader for MapNotify message.
258 */
259 public static final class NotifyWriter implements LispMessageWriter<LispMapNotify> {
260
Jian Liedc5db12016-08-23 17:30:19 +0900261 private static final int NOTIFY_SHIFT_BIT = 4;
262
263 private static final int UNUSED_ZERO = 0;
264
265 @Override
266 public void writeTo(ByteBuf byteBuf, LispMapNotify message) throws LispWriterException {
267
268 // specify LISP message type
Jian Licbc57e32016-09-14 09:06:54 +0900269 byte msgType = (byte) (LispType.LISP_MAP_NOTIFY.getTypeCode() << NOTIFY_SHIFT_BIT);
Jian Liedc5db12016-08-23 17:30:19 +0900270 byteBuf.writeByte(msgType);
271
272 // reserved field
273 byteBuf.writeShort((short) UNUSED_ZERO);
274
275 // record count
Jian Li42b3e432016-08-31 01:05:20 +0900276 byteBuf.writeByte(message.getMapRecords().size());
Jian Liedc5db12016-08-23 17:30:19 +0900277
278 // nonce
279 byteBuf.writeLong(message.getNonce());
280
281 // keyId
282 byteBuf.writeShort(message.getKeyId());
283
Jian Lif8c2d4a2016-09-15 02:33:12 +0900284 // authentication data and its length
285 if (message.getAuthenticationData() == null) {
286 byteBuf.writeShort((short) 0);
287 } else {
288 byteBuf.writeShort(message.getAuthenticationData().length);
289 byteBuf.writeBytes(message.getAuthenticationData());
Jian Liedc5db12016-08-23 17:30:19 +0900290 }
291
Jian Liedc5db12016-08-23 17:30:19 +0900292 // serialize map records
293 MapRecordWriter writer = new MapRecordWriter();
294 List<LispMapRecord> records = message.getMapRecords();
295
296 for (int i = 0; i < records.size(); i++) {
297 writer.writeTo(byteBuf, records.get(i));
298 }
299 }
300 }
Jian Li451175e2016-07-19 23:22:20 +0900301}