BUG-55: make sure session initialization asynchronous
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / PCEPRROSubobjectParser.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.RROAttributesSubobjectParser;
21 import org.opendaylight.protocol.pcep.impl.subobject.RROIPv4AddressSubobjectParser;
22 import org.opendaylight.protocol.pcep.impl.subobject.RROIPv6AddressSubobjectParser;
23 import org.opendaylight.protocol.pcep.impl.subobject.RROLabelSubobjectParser;
24 import org.opendaylight.protocol.pcep.impl.subobject.RROPathKeyWith128PCEIDSubobjectParser;
25 import org.opendaylight.protocol.pcep.impl.subobject.RROPathKeyWith32PCEIDSubobjectParser;
26 import org.opendaylight.protocol.pcep.impl.subobject.RROProtectionSubobjectParser;
27 import org.opendaylight.protocol.pcep.impl.subobject.RROUnnumberedInterfaceSubobjectParser;
28 import org.opendaylight.protocol.pcep.subobject.RROAttributesSubobject;
29 import org.opendaylight.protocol.pcep.subobject.RROIPAddressSubobject;
30 import org.opendaylight.protocol.pcep.subobject.RROLabelSubobject;
31 import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith128PCEIDSubobject;
32 import org.opendaylight.protocol.pcep.subobject.RROPathKeyWith32PCEIDSubobject;
33 import org.opendaylight.protocol.pcep.subobject.RROProtectionSubobject;
34 import org.opendaylight.protocol.pcep.subobject.RROUnnumberedInterfaceSubobject;
35 import org.opendaylight.protocol.pcep.subobject.ReportedRouteSubobject;
36
37 /**
38  * Parser for {@link org.opendaylight.protocol.pcep.PCEPSubobject PCEPSubobject}
39  */
40 public class PCEPRROSubobjectParser {
41
42     private static final Logger logger = LoggerFactory.getLogger(PCEPRROSubobjectParser.class);
43
44     /**
45      * Type identifier for {@link org.opendaylight.protocol.pcep.PCEPSubobject
46      * PCEPSubobject}
47      */
48     public enum PCEPSubobjectType {
49         IPv4_PREFIX(1), IPv6_PREFIX(2), LABEL(3), UNNUMBERED_INTERFACE_ID(4), ATTRIBUTES(5), PROTECTION(37), PK_32(64), PK_128(65);
50
51         private final int indicator;
52
53         PCEPSubobjectType(final int indicator) {
54             this.indicator = indicator;
55         }
56
57         public int getIndicator() {
58             return this.indicator;
59         }
60
61         public static PCEPSubobjectType getFromInt(final int type) throws PCEPDeserializerException {
62
63             for (final PCEPSubobjectType type_e : PCEPSubobjectType.values()) {
64                 if (type_e.getIndicator() == type)
65                     return type_e;
66             }
67
68             throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + "; Known: " + PCEPSubobjectType.values() + ".");
69         }
70         }
71
72     /*
73      * Fields lengths in Bytes
74      */
75     public static final int TYPE_F_LENGTH = 1;
76     public static final int LENGTH_F_LENGTH = 1;
77
78     /*
79      * Fields offsets in Bytes
80      */
81     public static final int TYPE_F_OFFSET = 0;
82     public static final int LENGTH_F_OFFSET = TYPE_F_OFFSET + TYPE_F_LENGTH;
83     public static final int SO_CONTENTS_OFFSET = LENGTH_F_OFFSET + LENGTH_F_LENGTH;
84
85     public static List<ReportedRouteSubobject> parse(final byte[] bytes) throws PCEPDeserializerException {
86         if (bytes == null)
87             throw new IllegalArgumentException("Byte array is mandatory.");
88
89         final List<ReportedRouteSubobject> subobjsList = new ArrayList<ReportedRouteSubobject>();
90         PCEPSubobjectType type;
91         byte[] soContentsBytes;
92         int length;
93         int offset = 0;
94
95         while (offset < bytes.length) {
96             length = ByteArray.bytesToInt(ByteArray.subByte(bytes, offset + LENGTH_F_OFFSET, LENGTH_F_LENGTH));
97
98             type = PCEPSubobjectType.getFromInt(bytes[offset + TYPE_F_OFFSET] & 0xff);
99
100             if (length > bytes.length - offset)
101                 throw new PCEPDeserializerException("Wrong length specified. Passed: " + length + "; Expected: <= " + (bytes.length - offset));
102
103             soContentsBytes = new byte[length - SO_CONTENTS_OFFSET];
104             System.arraycopy(bytes, offset + SO_CONTENTS_OFFSET, soContentsBytes, 0, length - SO_CONTENTS_OFFSET);
105
106             logger.trace("Attempt to parse subobject from bytes: {}", ByteArray.bytesToHexString(soContentsBytes));
107             final ReportedRouteSubobject subObj = parseSpecificSubobject(type, soContentsBytes);
108             logger.trace("Subobject was parsed. {}", subObj);
109
110             subobjsList.add(subObj);
111
112             offset += length;
113         }
114
115         return subobjsList;
116     }
117
118     public static byte[] put(final List<ReportedRouteSubobject> objsToSerialize) {
119         final List<byte[]> bytesList = new ArrayList<byte[]>(objsToSerialize.size());
120
121         int length = 0;
122         for (final ReportedRouteSubobject obj : objsToSerialize) {
123             final byte[] bytes = put(obj);
124             length += bytes.length;
125             bytesList.add(bytes);
126         }
127
128         final byte[] retBytes = new byte[length];
129
130         int offset = 0;
131         for (final byte[] bytes : bytesList) {
132             System.arraycopy(bytes, 0, retBytes, offset, bytes.length);
133             offset += bytes.length;
134         }
135
136         return retBytes;
137     }
138
139     public static byte[] put(final ReportedRouteSubobject objToSerialize) {
140         int typeIndicator = 0;
141
142         final byte[] soContentsBytes;
143
144         if (objToSerialize instanceof RROIPAddressSubobject<?> && ((RROIPAddressSubobject<?>) objToSerialize).getPrefix() instanceof IPv4Prefix) {
145             typeIndicator = PCEPSubobjectType.IPv4_PREFIX.getIndicator();
146             soContentsBytes = RROIPv4AddressSubobjectParser.put(objToSerialize);
147         } else if (objToSerialize instanceof RROIPAddressSubobject<?> && ((RROIPAddressSubobject<?>) objToSerialize).getPrefix() instanceof IPv6Prefix) {
148             typeIndicator = PCEPSubobjectType.IPv6_PREFIX.getIndicator();
149             soContentsBytes = RROIPv6AddressSubobjectParser.put(objToSerialize);
150         } else if (objToSerialize instanceof RROUnnumberedInterfaceSubobject) {
151             typeIndicator = PCEPSubobjectType.UNNUMBERED_INTERFACE_ID.getIndicator();
152             soContentsBytes = RROUnnumberedInterfaceSubobjectParser.put(objToSerialize);
153         } else if (objToSerialize instanceof RROLabelSubobject) {
154             typeIndicator = PCEPSubobjectType.LABEL.getIndicator();
155             soContentsBytes = RROLabelSubobjectParser.put((RROLabelSubobject) objToSerialize);
156         } else if (objToSerialize instanceof RROProtectionSubobject) {
157             typeIndicator = PCEPSubobjectType.PROTECTION.getIndicator();
158             soContentsBytes = RROProtectionSubobjectParser.put((RROProtectionSubobject) objToSerialize);
159         } else if (objToSerialize instanceof RROPathKeyWith32PCEIDSubobject) {
160             typeIndicator = PCEPSubobjectType.PK_32.getIndicator();
161             soContentsBytes = RROPathKeyWith32PCEIDSubobjectParser.put((RROPathKeyWith32PCEIDSubobject) objToSerialize);
162         } else if (objToSerialize instanceof RROPathKeyWith128PCEIDSubobject) {
163             typeIndicator = PCEPSubobjectType.PK_128.getIndicator();
164             soContentsBytes = RROPathKeyWith128PCEIDSubobjectParser.put((RROPathKeyWith128PCEIDSubobject) objToSerialize);
165         } else if (objToSerialize instanceof RROAttributesSubobject) {
166             typeIndicator = PCEPSubobjectType.ATTRIBUTES.getIndicator();
167             soContentsBytes = RROAttributesSubobjectParser.put((RROAttributesSubobject) objToSerialize);
168         } else
169             throw new IllegalArgumentException("Unknown instance of PCEPSubobject. Passed: " + objToSerialize.getClass() + ".");
170
171         final byte[] bytes = new byte[SO_CONTENTS_OFFSET + soContentsBytes.length];
172
173         bytes[TYPE_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(typeIndicator), (Integer.SIZE / 8) - TYPE_F_LENGTH)[0];
174         bytes[LENGTH_F_OFFSET] = ByteArray.cutBytes(ByteArray.intToBytes(soContentsBytes.length + SO_CONTENTS_OFFSET), (Integer.SIZE / 8) - LENGTH_F_LENGTH)[0];
175
176         System.arraycopy(soContentsBytes, 0, bytes, SO_CONTENTS_OFFSET, soContentsBytes.length);
177
178         return bytes;
179     }
180
181     private static ReportedRouteSubobject parseSpecificSubobject(final PCEPSubobjectType type, final byte[] soContentsBytes) throws PCEPDeserializerException {
182
183         switch (type) {
184             case IPv4_PREFIX:
185                 return RROIPv4AddressSubobjectParser.parse(soContentsBytes);
186             case IPv6_PREFIX:
187                 return RROIPv6AddressSubobjectParser.parse(soContentsBytes);
188             case UNNUMBERED_INTERFACE_ID:
189                 return RROUnnumberedInterfaceSubobjectParser.parse(soContentsBytes);
190             case LABEL:
191                 return RROLabelSubobjectParser.parse(soContentsBytes);
192             case PROTECTION:
193                 return RROProtectionSubobjectParser.parse(soContentsBytes);
194             case PK_32:
195                 return RROPathKeyWith32PCEIDSubobjectParser.parse(soContentsBytes);
196             case PK_128:
197                 return RROPathKeyWith128PCEIDSubobjectParser.parse(soContentsBytes);
198             case ATTRIBUTES:
199                 return RROAttributesSubobjectParser.parse(soContentsBytes);
200             default:
201                 throw new PCEPDeserializerException("Unknown Subobject type. Passed: " + type + ".");
202         }
203     }
204 }