927d83d6342137f9a1e790052887e3cc347cd261
[onosfw.git] /
1 /*
2  * Copyright 2015 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  */
16 package org.onosproject.pcepio.protocol.ver1;
17
18 import java.util.LinkedList;
19
20 import org.jboss.netty.buffer.ChannelBuffer;
21 import org.onosproject.pcepio.exceptions.PcepParseException;
22 import org.onosproject.pcepio.protocol.PcepErrorInfo;
23 import org.onosproject.pcepio.protocol.PcepErrorMsg;
24 import org.onosproject.pcepio.protocol.PcepErrorObject;
25 import org.onosproject.pcepio.protocol.PcepMessageReader;
26 import org.onosproject.pcepio.protocol.PcepMessageWriter;
27 import org.onosproject.pcepio.protocol.PcepOpenObject;
28 import org.onosproject.pcepio.protocol.PcepType;
29 import org.onosproject.pcepio.protocol.PcepVersion;
30 import org.onosproject.pcepio.types.ErrorObjListWithOpen;
31 import org.onosproject.pcepio.types.PcepObjectHeader;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import com.google.common.base.MoreObjects;
36 import com.google.common.base.MoreObjects.ToStringHelper;
37
38 /**
39  * Provides PCEP Error Message.
40  */
41 public class PcepErrorMsgVer1 implements PcepErrorMsg {
42
43     /*
44      * PCE Error message format.
45
46        <PCErr Message>                ::= <Common Header>
47                                         ( <error-obj-list> [<Open>] ) | <error>
48                                           [<error-list>]
49
50        <error-obj-list>               ::=<PCEP-ERROR>[<error-obj-list>]
51
52        <error>                        ::=[<request-id-list> | <te-id-list>]
53                                            <error-obj-list>
54
55        <request-id-list>              ::=<RP>[<request-id-list>]
56
57        <te-id-list>                   ::=<TE>[<te-id-list>]
58
59        <error-list>                   ::=<error>[<error-list>]
60      */
61
62     protected static final Logger log = LoggerFactory.getLogger(PcepOpenMsgVer1.class);
63     public static final byte PACKET_VERSION = 1;
64     public static final int PACKET_MINIMUM_LENGTH = 12;
65     public static final PcepType MSG_TYPE = PcepType.ERROR;
66
67     //Below either one should be present.
68     private ErrorObjListWithOpen errObjListWithOpen; //optional   ( <error-obj-list> [<Open>] )
69     private PcepErrorInfo errInfo; //optional     <error> [<error-list>]
70
71     public static final PcepErrorMsgVer1.Reader READER = new Reader();
72
73     /**
74      * constructor to initialize variables.
75      */
76     public PcepErrorMsgVer1() {
77         errObjListWithOpen = null;
78         errInfo = null;
79     }
80
81     /**
82      * Constructor to initialize variables.
83      *
84      * @param errObjListWithOpen error-object-list with open object
85      * @param errInfo error information
86      */
87     public PcepErrorMsgVer1(ErrorObjListWithOpen errObjListWithOpen, PcepErrorInfo errInfo) {
88         this.errObjListWithOpen = errObjListWithOpen;
89         this.errInfo = errInfo;
90     }
91
92     /**
93      * Reader class for reading PCEP error Message from channel buffer.
94      */
95     public static class Reader implements PcepMessageReader<PcepErrorMsg> {
96
97         ErrorObjListWithOpen errObjListWithOpen;
98         PcepErrorInfo errInfo;
99         PcepObjectHeader tempObjHeader;
100
101         @Override
102         public PcepErrorMsg readFrom(ChannelBuffer cb) throws PcepParseException {
103
104             errObjListWithOpen = null;
105             errInfo = null;
106             tempObjHeader = null;
107
108             if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
109                 throw new PcepParseException("Packet size is less than the minimum length.");
110             }
111
112             byte version = cb.readByte();
113             version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG);
114             if (version != PACKET_VERSION) {
115                 throw new PcepParseException("Wrong version: Expected=PcepVersion.PCEP_1(1), got=" + version);
116             }
117             // fixed value property type == 1
118             byte type = cb.readByte();
119             if (type != MSG_TYPE.getType()) {
120                 throw new PcepParseException("Wrong type: Expected=PcepType.ERROR(6), got=" + type);
121             }
122             int length = cb.readShort();
123             if (length < PACKET_MINIMUM_LENGTH) {
124                 throw new PcepParseException(
125                         "Wrong length: Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: " + length);
126             }
127
128             //parse <PCErr Message>
129             parsePCErrMsg(cb);
130
131             // If other than RP or TE or PCEP-ERROR present then it is error.
132             if (0 < cb.readableBytes()) {
133                 PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb);
134                 throw new PcepParseException("Unexpected Object found. Object Class : " + tempObjHeader.getObjClass());
135             }
136
137             return new PcepErrorMsgVer1(errObjListWithOpen, errInfo);
138         }
139
140         /**
141          * Parsing PCErr Message.
142          *
143          * @param cb channel buffer.
144          * @throws PcepParseException if mandatory fields are missing
145          * output: this.errObjListWithOpen, this.errInfo
146          */
147         public void parsePCErrMsg(ChannelBuffer cb) throws PcepParseException {
148             //If PCEP-ERROR list is followed by OPEN Object then store into ErrorObjListWithOpen.
149             //     ( <error-obj-list> [<Open>]
150             //If PCEP-ERROR list is followed by RP or TE Object then store into errInfo. <error> [<error-list>]
151             //If only PCEP-ERROR list is present then store into ErrorObjListWithOpen.
152             PcepObjectHeader tempObjHeader;
153             LinkedList<PcepErrorObject> llErrObjList;
154
155             if (0 >= cb.readableBytes()) {
156                 throw new PcepParseException("PCEP-ERROR message came with empty objects.");
157             }
158
159             //parse PCEP-ERROR list
160             llErrObjList = new LinkedList<>();
161             tempObjHeader = parseErrorObjectList(llErrObjList, cb);
162
163             //check whether OPEN-OBJECT is present.
164             if ((tempObjHeader != null)
165                     && (tempObjHeader.getObjClass() == PcepOpenObjectVer1.OPEN_OBJ_CLASS)) {
166
167                 if (llErrObjList.isEmpty()) {
168                     throw new PcepParseException("<error-obj-list> should be present if OPEN-OBJECT exists");
169                 }
170
171                 PcepOpenObject pcepOpenObj = PcepOpenObjectVer1.read(cb);
172                 this.errObjListWithOpen = new ErrorObjListWithOpen(llErrObjList, pcepOpenObj);
173
174             } else if ((tempObjHeader != null) //check whether RP or TE Object is present.
175                     && ((tempObjHeader.getObjClass() == PcepRPObjectVer1.RP_OBJ_CLASS)
176                             || (tempObjHeader.getObjClass() == PcepTEObjectVer1.TE_OBJ_CLASS))) {
177
178                 this.errInfo = new PcepErrorInfoVer1(null, null, llErrObjList);
179                 this.errInfo.read(cb);
180
181             } else if (!llErrObjList.isEmpty()) {
182                 //If only PCEP-ERROR list is present then store it in errObjListWithOpen.
183                 this.errObjListWithOpen = new ErrorObjListWithOpen(llErrObjList);
184             } else {
185                 throw new PcepParseException("Empty PCEP-ERROR message.");
186             }
187         }
188
189         /**
190          * Parse error-obj-list.
191          *
192          * @param llErrObjList error object list output
193          * @param cb channel buffer input
194          * @throws PcepParseException if mandatory fields are missing
195          * @return error object header
196          */
197         public PcepObjectHeader parseErrorObjectList(LinkedList<PcepErrorObject> llErrObjList, ChannelBuffer cb)
198                 throws PcepParseException {
199             PcepObjectHeader tempObjHeader = null;
200
201             while (0 < cb.readableBytes()) {
202                 cb.markReaderIndex();
203                 tempObjHeader = PcepObjectHeader.read(cb);
204                 cb.resetReaderIndex();
205                 if (tempObjHeader.getObjClass() == PcepErrorObjectVer1.ERROR_OBJ_CLASS) {
206                     llErrObjList.add(PcepErrorObjectVer1.read(cb));
207                 } else {
208                     break;
209                 }
210             }
211             return tempObjHeader;
212         }
213     }
214
215     /**
216      * Builder class for PCEP error message.
217      */
218     public static class Builder implements PcepErrorMsg.Builder {
219         // Pcep error message fields
220
221         private ErrorObjListWithOpen errObjListWithOpen = null; //optional   ( <error-obj-list> [<Open>] )
222         private PcepErrorInfo errInfo = null; //optional     <error> [<error-list>]
223
224         @Override
225         public PcepVersion getVersion() {
226             return PcepVersion.PCEP_1;
227         }
228
229         @Override
230         public PcepType getType() {
231             return PcepType.ERROR;
232         }
233
234         @Override
235         public PcepErrorMsg build() {
236             return new PcepErrorMsgVer1(this.errObjListWithOpen, this.errInfo);
237         }
238
239         @Override
240         public ErrorObjListWithOpen getErrorObjListWithOpen() {
241             return this.errObjListWithOpen;
242         }
243
244         @Override
245         public Builder setErrorObjListWithOpen(ErrorObjListWithOpen errObjListWithOpen) {
246             this.errObjListWithOpen = errObjListWithOpen;
247             return this;
248         }
249
250         @Override
251         public PcepErrorInfo getPcepErrorInfo() {
252             return this.errInfo;
253         }
254
255         @Override
256         public Builder setPcepErrorInfo(PcepErrorInfo errInfo) {
257             this.errInfo = errInfo;
258             return this;
259         }
260     }
261
262     @Override
263     public void writeTo(ChannelBuffer cb) throws PcepParseException {
264         WRITER.write(cb, this);
265     }
266
267     public static final Writer WRITER = new Writer();
268
269     /**
270      * Writer class for writing PCEP error Message to channel buffer.
271      */
272     static class Writer implements PcepMessageWriter<PcepErrorMsgVer1> {
273         @Override
274         public void write(ChannelBuffer cb, PcepErrorMsgVer1 message) throws PcepParseException {
275             int startIndex = cb.writerIndex();
276             // first 3 bits set to version
277             cb.writeByte((byte) (PACKET_VERSION << PcepMessageVer1.SHIFT_FLAG));
278             // message type 0xC
279             cb.writeByte(MSG_TYPE.getType());
280             // length is length of variable message, will be updated at the end
281             // Store the position of message
282             // length in buffer
283             int msgLenIndex = cb.writerIndex();
284             cb.writeShort(0);
285             ErrorObjListWithOpen errObjListWithOpen = message.getErrorObjListWithOpen();
286             PcepErrorInfo errInfo = message.getPcepErrorInfo();
287
288             // write ( <error-obj-list> [<Open>] ) if exists.
289             // otherwise write <error> [<error-list>]
290
291             if ((errObjListWithOpen != null)
292                     && (errObjListWithOpen.isErrorObjListWithOpenPresent())) {
293                 errObjListWithOpen.write(cb);
294             } else if ((errInfo != null) && (errInfo.isErrorInfoPresent())) {
295                 errInfo.write(cb);
296             } else {
297                 throw new PcepParseException("Empty PCEP-ERROR message.");
298             }
299             // PcepErrorMessage message length field
300             int length = cb.writerIndex() - startIndex;
301             cb.setShort(msgLenIndex, (short) length);
302         }
303     }
304
305     @Override
306     public PcepVersion getVersion() {
307         return PcepVersion.PCEP_1;
308     }
309
310     @Override
311     public PcepType getType() {
312         return MSG_TYPE;
313     }
314
315     @Override
316     public ErrorObjListWithOpen getErrorObjListWithOpen() {
317         return this.errObjListWithOpen;
318     }
319
320     @Override
321     public void setErrorObjListWithOpen(ErrorObjListWithOpen errObjListWithOpen) {
322         this.errObjListWithOpen = errObjListWithOpen;
323     }
324
325     @Override
326     public PcepErrorInfo getPcepErrorInfo() {
327         return this.errInfo;
328     }
329
330     @Override
331     public void setPcepErrorInfo(PcepErrorInfo errInfo) {
332         this.errInfo = errInfo;
333     }
334
335     /**
336      * Return list of Error types.
337      *
338      * @return error types list
339      */
340     public LinkedList<Integer> getErrorType() {
341         LinkedList<Integer> llErrorType = new LinkedList<>();
342         if ((errObjListWithOpen != null)
343                 && (errObjListWithOpen.isErrorObjListWithOpenPresent())) {
344             llErrorType = errObjListWithOpen.getErrorType();
345         } else if ((errInfo != null) && (errInfo.isErrorInfoPresent())) {
346             llErrorType = errInfo.getErrorType();
347         }
348
349         return llErrorType;
350     }
351
352     /**
353      * Return list of Error values.
354      *
355      * @return error value list
356      */
357     public LinkedList<Integer> getErrorValue() {
358         LinkedList<Integer> llErrorValue = new LinkedList<>();
359         if ((errObjListWithOpen != null)
360                 && (errObjListWithOpen.isErrorObjListWithOpenPresent())) {
361             llErrorValue = errObjListWithOpen.getErrorValue();
362         } else if ((errInfo != null) && (errInfo.isErrorInfoPresent())) {
363             llErrorValue = errInfo.getErrorValue();
364         }
365
366         return llErrorValue;
367     }
368
369     @Override
370     public String toString() {
371         ToStringHelper toStrHelper = MoreObjects.toStringHelper(getClass());
372
373         if ((errObjListWithOpen != null)
374                 && (errObjListWithOpen.isErrorObjListWithOpenPresent())) {
375             toStrHelper.add("ErrorObjectListWithOpen", errObjListWithOpen);
376         }
377         if ((errInfo != null) && (errInfo.isErrorInfoPresent())) {
378             toStrHelper.add("ErrorInfo", errInfo);
379         }
380
381         return toStrHelper.toString();
382     }
383 }