Revert "BUG-47 : unfinished PCEP migration to generated DTOs."
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / PCEPEROSubobjectParser.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.pcep.impl;
9
10 import java.util.ArrayList;
11 import java.util.List;
12
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15
16 import org.opendaylight.protocol.util.ByteArray;
17 import org.opendaylight.protocol.concepts.IPv4Prefix;
18 import org.opendaylight.protocol.concepts.IPv6Prefix;
19 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
20 import org.opendaylight.protocol.pcep.impl.subobject.EROAsNumberSubobjectParser;
21 import org.opendaylight.protocol.pcep.impl.subobject.EROExplicitExclusionRouteSubobjectParser;
22 import org.opendaylight.protocol.pcep.impl.subobject.EROIPv4PrefixSubobjectParser;
23 import org.opendaylight.protocol.pcep.impl.subobject.EROIPv6PrefixSubobjectParser;
24 import org.opendaylight.protocol.pcep.impl.subobject.EROLabelSubobjectParser;
25 import org.opendaylight.protocol.pcep.impl.subobject.EROPathKeyWith128PCEIDSubobjectParser;
26 import org.opendaylight.protocol.pcep.impl.subobject.EROPathKeyWith32PCEIDSubobjectParser;
27 import org.opendaylight.protocol.pcep.impl.subobject.EROProtectionSubobjectParser;
28 import org.opendaylight.protocol.pcep.impl.subobject.EROUnnumberedInterfaceSubobjectParser;
29 import org.opendaylight.protocol.pcep.subobject.EROAsNumberSubobject;
30 import org.opendaylight.protocol.pcep.subobject.EROExplicitExclusionRouteSubobject;
31 import org.opendaylight.protocol.pcep.subobject.EROIPPrefixSubobject;
32 import org.opendaylight.protocol.pcep.subobject.EROLabelSubobject;
33 import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith128PCEIDSubobject;
34 import org.opendaylight.protocol.pcep.subobject.EROPathKeyWith32PCEIDSubobject;
35 import org.opendaylight.protocol.pcep.subobject.EROProtectionSubobject;
36 import org.opendaylight.protocol.pcep.subobject.EROUnnumberedInterfaceSubobject;
37 import org.opendaylight.protocol.pcep.subobject.ExplicitRouteSubobject;
38
39 /**
40  * Parser for {@link org.opendaylight.protocol.pcep.PCEPSubobject PCEPSubobject}
41  */
42 public class PCEPEROSubobjectParser {
43
44     private static final Logger logger = LoggerFactory.getLogger(PCEPEROSubobjectParser.class);
45
46     /**
47      * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPSubobject
48      * PCEPSubobject}
49      */
50     public enum PCEPSubobjectType {
51                 IPv4_PREFIX(1), IPv6_PREFIX(2), LABEL(3), UNNUMBERED_INTERFACE_ID(4), AS_NUMBER(32), EXRS(33), PROTECTION(37), PK_32(
52                                 64), PK_128(65);
53
54                 private final int indicator;
55
56                 PCEPSubobjectType(int indicator) {
57                         this.indicator = indicator;
58                 }
59
60                 public int getIndicator() {
61                         return this.indicator;
62                 }
63
64                 public static PCEPSubobjectType getFromInt(int type) throws PCEPDeserializerException {
65
66                         for (final PCEPSubobjectType type_e : PCEPSubobjectType.values()) {
67                                 if (type_e.getIndicator() == type)
68                                         return type_e;
69                         }
70
71                         throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + "; Known: "
72                                         + PCEPSubobjectType.values() + ".");
73                 }
74         }
75
76     /*
77      * Fields lengths in Bytes
78      */
79     public static final int TYPE_FLAG_F_LENGTH = 1;
80     public static final int LENGTH_F_LENGTH = 1;
81
82     /*
83      * Fields offsets in Bytes
84      */
85     public static final int TYPE_FLAG_F_OFFSET = 0;
86     public static final int LENGTH_F_OFFSET = TYPE_FLAG_F_OFFSET + TYPE_FLAG_F_LENGTH;
87     public static final int SO_CONTENTS_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
88
89     public static List<ExplicitRouteSubobject> parse(byte[] bytes) throws PCEPDeserializerException {
90         if (bytes == null)
91             throw new IllegalArgumentException("Byte array is mandatory.");
92
93         final List<ExplicitRouteSubobject> subobjsList = new ArrayList<ExplicitRouteSubobject>();
94         boolean loose_flag;
95         PCEPSubobjectType type;
96         byte[] soContentsBytes;
97         int length;
98         int offset = 0;
99
100         while (offset < bytes.length) {
101
102             loose_flag = ((bytes[offset + TYPE_FLAG_F_OFFSET] & (1 << 7)) != 0) ? true : false;
103             length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
104
105             type = PCEPSubobjectType.getFromInt((bytes[offset + TYPE_FLAG_F_OFFSET] & 0xff) & ~(1 << 7));
106
107             if (length > bytes.length - offset)
108                 throw new PCEPDeserializerException("Wrong length specified. Passed: " + length + "; Expected: <= " + (bytes.length - offset));
109
110             soContentsBytes = new byte[length - SO_CONTENTS_OFFSET];
111             System.arraycopy(bytes, offset + SO_CONTENTS_OFFSET, soContentsBytes, 0, length - SO_CONTENTS_OFFSET);
112
113             logger.debug("Attempt to parse subobject from bytes: {}", ByteArray.bytesToHexString(soContentsBytes));
114             final ExplicitRouteSubobject subObj = parseSpecificSubobject(type, soContentsBytes, loose_flag);
115             logger.debug("Subobject was parsed. {}", subObj);
116
117             subobjsList.add(subObj);
118
119             offset += length;
120         }
121
122         return subobjsList;
123     }
124
125     public static byte[] put(List<ExplicitRouteSubobject> objsToSerialize) {
126         final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
127
128         int length = 0;
129         for (final ExplicitRouteSubobject obj : objsToSerialize) {
130             final byte[] bytes = put(obj);
131             length += bytes.length;
132             bytesList.add(bytes);
133         }
134
135         final byte[] retBytes = new byte[length];
136
137         int offset = 0;
138         for (final byte[] bytes : bytesList) {
139             System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
140             offset += bytes.length;
141         }
142
143         return retBytes;
144     }
145
146     public static byte[] put(ExplicitRouteSubobject objToSerialize) {
147         int typeIndicator = 0;
148
149         final byte[] soContentsBytes;
150
151         if (objToSerialize instanceof EROIPPrefixSubobject<?> && ((EROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv4Prefix) {
152             typeIndicator = PCEPSubobjectType.IPv4_PREFIX.getIndicator();
153             soContentsBytes = EROIPv4PrefixSubobjectParser.put(objToSerialize);
154         } else if (objToSerialize instanceof EROIPPrefixSubobject<?> && ((EROIPPrefixSubobject<?>) objToSerialize).getPrefix() instanceof IPv6Prefix) {
155             typeIndicator = PCEPSubobjectType.IPv6_PREFIX.getIndicator();
156             soContentsBytes = EROIPv6PrefixSubobjectParser.put(objToSerialize);
157         } else if (objToSerialize instanceof EROAsNumberSubobject) {
158             typeIndicator = PCEPSubobjectType.AS_NUMBER.getIndicator();
159             soContentsBytes = EROAsNumberSubobjectParser.put(objToSerialize);
160         } else if (objToSerialize instanceof EROUnnumberedInterfaceSubobject) {
161             typeIndicator = PCEPSubobjectType.UNNUMBERED_INTERFACE_ID.getIndicator();
162             soContentsBytes = EROUnnumberedInterfaceSubobjectParser.put(objToSerialize);
163         } else if (objToSerialize instanceof EROLabelSubobject) {
164             typeIndicator = PCEPSubobjectType.LABEL.getIndicator();
165             soContentsBytes = EROLabelSubobjectParser.put((EROLabelSubobject) objToSerialize);
166         } else if (objToSerialize instanceof EROExplicitExclusionRouteSubobject) {
167             typeIndicator = PCEPSubobjectType.EXRS.getIndicator();
168             soContentsBytes = EROExplicitExclusionRouteSubobjectParser.put((EROExplicitExclusionRouteSubobject) objToSerialize);
169         } else if (objToSerialize instanceof EROPathKeyWith32PCEIDSubobject) {
170             typeIndicator = PCEPSubobjectType.PK_32.getIndicator();
171             soContentsBytes = EROPathKeyWith32PCEIDSubobjectParser.put((EROPathKeyWith32PCEIDSubobject) objToSerialize);
172         } else if (objToSerialize instanceof EROPathKeyWith128PCEIDSubobject) {
173             typeIndicator = PCEPSubobjectType.PK_128.getIndicator();
174             soContentsBytes = EROPathKeyWith128PCEIDSubobjectParser.put((EROPathKeyWith128PCEIDSubobject) objToSerialize);
175         } else if (objToSerialize instanceof EROProtectionSubobject) {
176             typeIndicator = PCEPSubobjectType.PROTECTION.getIndicator();
177             soContentsBytes = EROProtectionSubobjectParser.put((EROProtectionSubobject) objToSerialize);
178         } else
179             throw new IllegalArgumentException("Unknown instance of PCEPSubobject. Passed: " + objToSerialize.getClass() + ".");
180
181         final byte[] bytes = new byte[SO_CONTENTS_OFFSET + soContentsBytes.length];
182
183         bytes[TYPE_FLAG_F_OFFSET] = (byte) (ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_FLAG_F_LENGTH)[0] | (objToSerialize
184                 .isLoose() ? 1 << 7 : 0));
185         bytes[LENGTH_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(soContentsBytes.length + SO_CONTENTS_OFFSET), (Integer.SIZE / 8) - LENGTH_F_LENGTH)[0];
186
187         System.arraycopy(soContentsBytes, 0, bytes, SO_CONTENTS_OFFSET, soContentsBytes.length);
188
189         return bytes;
190     }
191
192     private static ExplicitRouteSubobject parseSpecificSubobject(PCEPSubobjectType type, byte[] soContentsBytes, boolean loose_flag)
193             throws PCEPDeserializerException {
194
195         switch (type) {
196             case IPv4_PREFIX:
197                 return EROIPv4PrefixSubobjectParser.parse(soContentsBytes, loose_flag);
198             case IPv6_PREFIX:
199                 return EROIPv6PrefixSubobjectParser.parse(soContentsBytes, loose_flag);
200             case UNNUMBERED_INTERFACE_ID:
201                 return EROUnnumberedInterfaceSubobjectParser.parse(soContentsBytes, loose_flag);
202             case AS_NUMBER:
203                 return EROAsNumberSubobjectParser.parse(soContentsBytes, loose_flag);
204             case LABEL:
205                 return EROLabelSubobjectParser.parse(soContentsBytes, loose_flag);
206             case EXRS:
207                 return EROExplicitExclusionRouteSubobjectParser.parse(soContentsBytes, loose_flag);
208             case PK_32:
209                 return EROPathKeyWith32PCEIDSubobjectParser.parse(soContentsBytes, loose_flag);
210             case PK_128:
211                 return EROPathKeyWith128PCEIDSubobjectParser.parse(soContentsBytes, loose_flag);
212             case PROTECTION:
213                 return EROProtectionSubobjectParser.parse(soContentsBytes, loose_flag);
214             default:
215                 throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + ".");
216         }
217     }
218 }