2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.protocol.pcep.impl.object;
11 import java.util.List;
13 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
14 import org.opendaylight.protocol.pcep.PCEPDocumentedException;
15 import org.opendaylight.protocol.pcep.PCEPErrors;
16 import org.opendaylight.protocol.pcep.PCEPObject;
17 import org.opendaylight.protocol.pcep.PCEPTlv;
18 import org.opendaylight.protocol.pcep.impl.PCEPObjectParser;
19 import org.opendaylight.protocol.pcep.impl.PCEPTlvParser;
20 import org.opendaylight.protocol.pcep.impl.Util;
21 import org.opendaylight.protocol.pcep.object.PCEPOpenObject;
22 import org.opendaylight.protocol.pcep.tlv.OFListTlv;
23 import org.opendaylight.protocol.util.ByteArray;
24 import com.google.common.primitives.UnsignedBytes;
27 * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPOpenObject PCEPOpenObject}
30 public class PCEPOpenObjectParser implements PCEPObjectParser {
33 * lengths of fields in bytes
35 public static final int VER_FLAGS_MF_LENGTH = 1; // multi-field
36 public static final int KEEPALIVE_F_LENGTH = 1;
37 public static final int DEAD_TIMER_LENGTH = 1;
38 public static final int SID_F_LENGTH = 1;
41 * lengths of subfields inside multi-field in bits
43 public static final int VERSION_SF_LENGTH = 3;
44 public static final int FLAGS_SF_LENGTH = 5;
47 * offsets of field in bytes
50 public static final int VER_FLAGS_MF_OFFSET = 0;
51 public static final int KEEPALIVE_F_OFFSET = VER_FLAGS_MF_OFFSET + VER_FLAGS_MF_LENGTH;
52 public static final int DEAD_TIMER_OFFSET = KEEPALIVE_F_OFFSET + KEEPALIVE_F_LENGTH;
53 public static final int SID_F_OFFSET = DEAD_TIMER_OFFSET + DEAD_TIMER_LENGTH;
54 public static final int TLVS_OFFSET = SID_F_OFFSET + SID_F_LENGTH;
57 * offsets of subfields inside multi-field in bits
60 public static final int VERSION_SF_OFFSET = 0;
61 public static final int FLAGS_SF_OFFSET = VERSION_SF_LENGTH + VERSION_SF_OFFSET;
63 public static final int PADDED_TO = 4;
66 public PCEPOpenObject parse(byte[] bytes, boolean processed, boolean ignored) throws PCEPDeserializerException, PCEPDocumentedException {
67 if (bytes == null || bytes.length == 0)
68 throw new IllegalArgumentException("Array of bytes is mandatory. Can't be null or empty.");
70 if (bytes.length < TLVS_OFFSET)
71 throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
74 final int versionValue = ByteArray.copyBitsRange(bytes[VER_FLAGS_MF_OFFSET], VERSION_SF_OFFSET, VERSION_SF_LENGTH);
76 if (versionValue != PCEPOpenObject.PCEP_VERSION)
77 throw new PCEPDocumentedException("Unsupported PCEP version " + versionValue, PCEPErrors.PCEP_VERSION_NOT_SUPPORTED);
79 final List<PCEPTlv> tlvs = PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET));
80 boolean ofListOccure = false;
82 for (final PCEPTlv tlv : tlvs) {
83 if (tlv instanceof OFListTlv) {
85 throw new PCEPDocumentedException("Invalid or unexpected message", PCEPErrors.NON_OR_INVALID_OPEN_MSG);
91 return new PCEPOpenObject(UnsignedBytes.toInt(bytes[KEEPALIVE_F_OFFSET]), UnsignedBytes.toInt(bytes[DEAD_TIMER_OFFSET]),
92 UnsignedBytes.toInt(bytes[SID_F_OFFSET]), tlvs);
96 public byte[] put(PCEPObject obj) {
97 if (!(obj instanceof PCEPOpenObject))
98 throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPOpenObject.");
100 final PCEPOpenObject openObj = (PCEPOpenObject) obj;
102 final byte versionFlagMF = (byte) (PCEPOpenObject.PCEP_VERSION << (Byte.SIZE - VERSION_SF_LENGTH));
104 final byte[] tlvs = PCEPTlvParser.put(openObj.getTlvs());
105 final byte[] bytes = new byte[TLVS_OFFSET + tlvs.length + Util.getPadding(TLVS_OFFSET + tlvs.length, PADDED_TO)];
107 // serialize version_flags multi-field
108 bytes[VER_FLAGS_MF_OFFSET] = versionFlagMF;
110 // serialize keepalive
111 bytes[KEEPALIVE_F_OFFSET] = (byte) openObj.getKeepAliveTimerValue();
113 // serialize dead timer
114 bytes[DEAD_TIMER_OFFSET] = (byte) openObj.getDeadTimerValue();
117 bytes[SID_F_OFFSET] = (byte) openObj.getSessionId();
120 ByteArray.copyWhole(tlvs, bytes, TLVS_OFFSET);