| /* |
| * Copyright 2015-present Open Networking Laboratory |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.pcepio.protocol.ver1; |
| |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import org.jboss.netty.buffer.ChannelBuffer; |
| import org.onosproject.pcepio.exceptions.PcepParseException; |
| import org.onosproject.pcepio.protocol.PcepErrorInfo; |
| import org.onosproject.pcepio.protocol.PcepErrorMsg; |
| import org.onosproject.pcepio.protocol.PcepErrorObject; |
| import org.onosproject.pcepio.protocol.PcepMessageReader; |
| import org.onosproject.pcepio.protocol.PcepMessageWriter; |
| import org.onosproject.pcepio.protocol.PcepOpenObject; |
| import org.onosproject.pcepio.protocol.PcepType; |
| import org.onosproject.pcepio.protocol.PcepVersion; |
| import org.onosproject.pcepio.types.ErrorObjListWithOpen; |
| import org.onosproject.pcepio.types.PcepObjectHeader; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.common.base.MoreObjects; |
| import com.google.common.base.MoreObjects.ToStringHelper; |
| |
| /** |
| * Provides PCEP Error Message. |
| */ |
| public class PcepErrorMsgVer1 implements PcepErrorMsg { |
| |
| /* |
| * PCE Error message format. |
| Reference: draft-dhodylee-pce-pcep-ls-01, section 8.2. |
| |
| <PCErr Message> ::= <Common Header> |
| ( <error-obj-list> [<Open>] ) | <error> |
| [<error-list>] |
| |
| <error-obj-list> ::=<PCEP-ERROR>[<error-obj-list>] |
| |
| <error> ::=[<request-id-list> | <ls-id-list>] |
| <error-obj-list> |
| |
| <request-id-list> ::=<RP>[<request-id-list>] |
| |
| <ls-id-list> ::=<LS>[<ls-id-list>] |
| |
| <error-list> ::=<error>[<error-list>] |
| */ |
| |
| protected static final Logger log = LoggerFactory.getLogger(PcepOpenMsgVer1.class); |
| public static final byte PACKET_VERSION = 1; |
| public static final int PACKET_MINIMUM_LENGTH = 12; |
| public static final PcepType MSG_TYPE = PcepType.ERROR; |
| |
| //Below either one should be present. |
| private ErrorObjListWithOpen errObjListWithOpen; //optional ( <error-obj-list> [<Open>] ) |
| private PcepErrorInfo errInfo; //optional <error> [<error-list>] |
| |
| public static final PcepErrorMsgVer1.Reader READER = new Reader(); |
| |
| /** |
| * Constructor to initialize variables. |
| */ |
| public PcepErrorMsgVer1() { |
| errObjListWithOpen = null; |
| errInfo = null; |
| } |
| |
| /** |
| * Constructor to initialize variables. |
| * |
| * @param errObjListWithOpen error-object-list with open object |
| * @param errInfo error information |
| */ |
| public PcepErrorMsgVer1(ErrorObjListWithOpen errObjListWithOpen, PcepErrorInfo errInfo) { |
| this.errObjListWithOpen = errObjListWithOpen; |
| this.errInfo = errInfo; |
| } |
| |
| /** |
| * Reader class for reading PCEP error Message from channel buffer. |
| */ |
| public static class Reader implements PcepMessageReader<PcepErrorMsg> { |
| |
| ErrorObjListWithOpen errObjListWithOpen; |
| PcepErrorInfo errInfo; |
| PcepObjectHeader tempObjHeader; |
| |
| @Override |
| public PcepErrorMsg readFrom(ChannelBuffer cb) throws PcepParseException { |
| |
| errObjListWithOpen = null; |
| errInfo = null; |
| tempObjHeader = null; |
| |
| if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) { |
| throw new PcepParseException("Packet size is less than the minimum length."); |
| } |
| |
| byte version = cb.readByte(); |
| version = (byte) (version >> PcepMessageVer1.SHIFT_FLAG); |
| if (version != PACKET_VERSION) { |
| throw new PcepParseException("Wrong version: Expected=PcepVersion.PCEP_1(1), got=" + version); |
| } |
| // fixed value property type == 1 |
| byte type = cb.readByte(); |
| if (type != MSG_TYPE.getType()) { |
| throw new PcepParseException("Wrong type: Expected=PcepType.ERROR(6), got=" + type); |
| } |
| int length = cb.readShort(); |
| if (length < PACKET_MINIMUM_LENGTH) { |
| throw new PcepParseException( |
| "Wrong length: Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: " + length); |
| } |
| |
| //parse <PCErr Message> |
| parsePCErrMsg(cb); |
| |
| // If other than RP or LS or PCEP-ERROR present then it is error. |
| if (0 < cb.readableBytes()) { |
| PcepObjectHeader tempObjHeader = PcepObjectHeader.read(cb); |
| throw new PcepParseException("Unexpected Object found. Object Class : " + tempObjHeader.getObjClass()); |
| } |
| |
| return new PcepErrorMsgVer1(errObjListWithOpen, errInfo); |
| } |
| |
| /** |
| * Parsing PCErr Message. |
| * |
| * @param cb channel buffer. |
| * @throws PcepParseException if mandatory fields are missing |
| * output: this.errObjListWithOpen, this.errInfo |
| */ |
| public void parsePCErrMsg(ChannelBuffer cb) throws PcepParseException { |
| //If PCEP-ERROR list is followed by OPEN Object then store into ErrorObjListWithOpen. |
| // ( <error-obj-list> [<Open>] |
| //If PCEP-ERROR list is followed by RP or LS Object then store into errInfo. <error> [<error-list>] |
| //If only PCEP-ERROR list is present then store into ErrorObjListWithOpen. |
| PcepObjectHeader tempObjHeader; |
| List<PcepErrorObject> llErrObjList; |
| |
| if (0 >= cb.readableBytes()) { |
| throw new PcepParseException("PCEP-ERROR message came with empty objects."); |
| } |
| |
| //parse PCEP-ERROR list |
| llErrObjList = new LinkedList<>(); |
| tempObjHeader = parseErrorObjectList(llErrObjList, cb); |
| |
| //check whether OPEN-OBJECT is present. |
| if ((tempObjHeader != null) |
| && (tempObjHeader.getObjClass() == PcepOpenObjectVer1.OPEN_OBJ_CLASS)) { |
| |
| if (llErrObjList.isEmpty()) { |
| throw new PcepParseException("<error-obj-list> should be present if OPEN-OBJECT exists"); |
| } |
| |
| PcepOpenObject pcepOpenObj = PcepOpenObjectVer1.read(cb); |
| this.errObjListWithOpen = new ErrorObjListWithOpen(llErrObjList, pcepOpenObj); |
| |
| } else if ((tempObjHeader != null) //check whether RP or LS Object is present. |
| && ((tempObjHeader.getObjClass() == PcepRPObjectVer1.RP_OBJ_CLASS) |
| || (tempObjHeader.getObjClass() == PcepLSObjectVer1.LS_OBJ_CLASS))) { |
| |
| this.errInfo = new PcepErrorInfoVer1(null, null, llErrObjList); |
| this.errInfo.read(cb); |
| |
| } else if (!llErrObjList.isEmpty()) { |
| //If only PCEP-ERROR list is present then store it in errObjListWithOpen. |
| this.errObjListWithOpen = new ErrorObjListWithOpen(llErrObjList); |
| } else { |
| throw new PcepParseException("Empty PCEP-ERROR message."); |
| } |
| } |
| |
| /** |
| * Parse error-obj-list. |
| * |
| * @param llErrObjList error object list output |
| * @param cb channel buffer input |
| * @throws PcepParseException if mandatory fields are missing |
| * @return error object header |
| */ |
| public PcepObjectHeader parseErrorObjectList(List<PcepErrorObject> llErrObjList, ChannelBuffer cb) |
| throws PcepParseException { |
| PcepObjectHeader tempObjHeader = null; |
| |
| while (0 < cb.readableBytes()) { |
| cb.markReaderIndex(); |
| tempObjHeader = PcepObjectHeader.read(cb); |
| cb.resetReaderIndex(); |
| if (tempObjHeader.getObjClass() == PcepErrorObjectVer1.ERROR_OBJ_CLASS) { |
| llErrObjList.add(PcepErrorObjectVer1.read(cb)); |
| } else { |
| break; |
| } |
| } |
| return tempObjHeader; |
| } |
| } |
| |
| /** |
| * Builder class for PCEP error message. |
| */ |
| public static class Builder implements PcepErrorMsg.Builder { |
| // Pcep error message fields |
| |
| private ErrorObjListWithOpen errObjListWithOpen = null; //optional ( <error-obj-list> [<Open>] ) |
| private PcepErrorInfo errInfo = null; //optional <error> [<error-list>] |
| |
| @Override |
| public PcepVersion getVersion() { |
| return PcepVersion.PCEP_1; |
| } |
| |
| @Override |
| public PcepType getType() { |
| return PcepType.ERROR; |
| } |
| |
| @Override |
| public PcepErrorMsg build() { |
| return new PcepErrorMsgVer1(this.errObjListWithOpen, this.errInfo); |
| } |
| |
| @Override |
| public ErrorObjListWithOpen getErrorObjListWithOpen() { |
| return this.errObjListWithOpen; |
| } |
| |
| @Override |
| public Builder setErrorObjListWithOpen(ErrorObjListWithOpen errObjListWithOpen) { |
| this.errObjListWithOpen = errObjListWithOpen; |
| return this; |
| } |
| |
| @Override |
| public PcepErrorInfo getPcepErrorInfo() { |
| return this.errInfo; |
| } |
| |
| @Override |
| public Builder setPcepErrorInfo(PcepErrorInfo errInfo) { |
| this.errInfo = errInfo; |
| return this; |
| } |
| } |
| |
| @Override |
| public void writeTo(ChannelBuffer cb) throws PcepParseException { |
| WRITER.write(cb, this); |
| } |
| |
| public static final Writer WRITER = new Writer(); |
| |
| /** |
| * Writer class for writing PCEP error Message to channel buffer. |
| */ |
| static class Writer implements PcepMessageWriter<PcepErrorMsgVer1> { |
| @Override |
| public void write(ChannelBuffer cb, PcepErrorMsgVer1 message) throws PcepParseException { |
| int startIndex = cb.writerIndex(); |
| // first 3 bits set to version |
| cb.writeByte((byte) (PACKET_VERSION << PcepMessageVer1.SHIFT_FLAG)); |
| // message type 0xC |
| cb.writeByte(MSG_TYPE.getType()); |
| // length is length of variable message, will be updated at the end |
| // Store the position of message |
| // length in buffer |
| int msgLenIndex = cb.writerIndex(); |
| cb.writeShort(0); |
| ErrorObjListWithOpen errObjListWithOpen = message.getErrorObjListWithOpen(); |
| PcepErrorInfo errInfo = message.getPcepErrorInfo(); |
| |
| // write ( <error-obj-list> [<Open>] ) if exists. |
| // otherwise write <error> [<error-list>] |
| |
| if ((errObjListWithOpen != null) |
| && (errObjListWithOpen.isErrorObjListWithOpenPresent())) { |
| errObjListWithOpen.write(cb); |
| } else if ((errInfo != null) && (errInfo.isErrorInfoPresent())) { |
| errInfo.write(cb); |
| } else { |
| throw new PcepParseException("Empty PCEP-ERROR message."); |
| } |
| // PcepErrorMessage message length field |
| int length = cb.writerIndex() - startIndex; |
| cb.setShort(msgLenIndex, (short) length); |
| } |
| } |
| |
| @Override |
| public PcepVersion getVersion() { |
| return PcepVersion.PCEP_1; |
| } |
| |
| @Override |
| public PcepType getType() { |
| return MSG_TYPE; |
| } |
| |
| @Override |
| public ErrorObjListWithOpen getErrorObjListWithOpen() { |
| return this.errObjListWithOpen; |
| } |
| |
| @Override |
| public void setErrorObjListWithOpen(ErrorObjListWithOpen errObjListWithOpen) { |
| this.errObjListWithOpen = errObjListWithOpen; |
| } |
| |
| @Override |
| public PcepErrorInfo getPcepErrorInfo() { |
| return this.errInfo; |
| } |
| |
| @Override |
| public void setPcepErrorInfo(PcepErrorInfo errInfo) { |
| this.errInfo = errInfo; |
| } |
| |
| /** |
| * Return list of Error types. |
| * |
| * @return error types list |
| */ |
| public List<Integer> getErrorType() { |
| List<Integer> llErrorType = new LinkedList<>(); |
| if ((errObjListWithOpen != null) |
| && (errObjListWithOpen.isErrorObjListWithOpenPresent())) { |
| llErrorType = errObjListWithOpen.getErrorType(); |
| } else if ((errInfo != null) && (errInfo.isErrorInfoPresent())) { |
| llErrorType = errInfo.getErrorType(); |
| } |
| |
| return llErrorType; |
| } |
| |
| /** |
| * Return list of Error values. |
| * |
| * @return error value list |
| */ |
| public List<Integer> getErrorValue() { |
| List<Integer> llErrorValue = new LinkedList<>(); |
| if ((errObjListWithOpen != null) |
| && (errObjListWithOpen.isErrorObjListWithOpenPresent())) { |
| llErrorValue = errObjListWithOpen.getErrorValue(); |
| } else if ((errInfo != null) && (errInfo.isErrorInfoPresent())) { |
| llErrorValue = errInfo.getErrorValue(); |
| } |
| |
| return llErrorValue; |
| } |
| |
| @Override |
| public String toString() { |
| ToStringHelper toStrHelper = MoreObjects.toStringHelper(getClass()).omitNullValues(); |
| |
| if ((errObjListWithOpen != null) |
| && (errObjListWithOpen.isErrorObjListWithOpenPresent())) { |
| toStrHelper.add("ErrorObjectListWithOpen", errObjListWithOpen); |
| } |
| if ((errInfo != null) && (errInfo.isErrorInfoPresent())) { |
| toStrHelper.add("ErrorInfo", errInfo); |
| } |
| |
| return toStrHelper.toString(); |
| } |
| } |