Revert "BUG-47 : unfinished PCEP migration to generated DTOs."
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / object / PCEPOpenObjectParser.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
9 package org.opendaylight.protocol.pcep.impl.object;
10
11 import java.util.List;
12
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;
25
26 /**
27  * Parser for {@link org.opendaylight.protocol.pcep.object.PCEPOpenObject PCEPOpenObject}
28  */
29
30 public class PCEPOpenObjectParser implements PCEPObjectParser {
31
32         /*
33          * lengths of fields in bytes
34          */
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;
39
40         /*
41          * lengths of subfields inside multi-field in bits
42          */
43         public static final int VERSION_SF_LENGTH = 3;
44         public static final int FLAGS_SF_LENGTH = 5;
45
46         /*
47          * offsets of field in bytes
48          */
49
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;
55
56         /*
57          * offsets of subfields inside multi-field in bits
58          */
59
60         public static final int VERSION_SF_OFFSET = 0;
61         public static final int FLAGS_SF_OFFSET = VERSION_SF_LENGTH + VERSION_SF_OFFSET;
62
63         public static final int PADDED_TO = 4;
64
65         @Override
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.");
69
70                 if (bytes.length < TLVS_OFFSET)
71                         throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.length + "; Expected: >=" + TLVS_OFFSET + ".");
72
73                 // parse version
74                 final int versionValue = ByteArray.copyBitsRange(bytes[VER_FLAGS_MF_OFFSET], VERSION_SF_OFFSET, VERSION_SF_LENGTH);
75
76                 if (versionValue != PCEPOpenObject.PCEP_VERSION)
77                         throw new PCEPDocumentedException("Unsupported PCEP version " + versionValue, PCEPErrors.PCEP_VERSION_NOT_SUPPORTED);
78
79                 final List<PCEPTlv> tlvs = PCEPTlvParser.parse(ByteArray.cutBytes(bytes, TLVS_OFFSET));
80                 boolean ofListOccure = false;
81
82                 for (final PCEPTlv tlv : tlvs) {
83                         if (tlv instanceof OFListTlv) {
84                                 if (ofListOccure)
85                                         throw new PCEPDocumentedException("Invalid or unexpected message", PCEPErrors.NON_OR_INVALID_OPEN_MSG);
86
87                                 ofListOccure = true;
88                         }
89                 }
90
91                 return new PCEPOpenObject(UnsignedBytes.toInt(bytes[KEEPALIVE_F_OFFSET]), UnsignedBytes.toInt(bytes[DEAD_TIMER_OFFSET]),
92                                 UnsignedBytes.toInt(bytes[SID_F_OFFSET]), tlvs);
93         }
94
95         @Override
96         public byte[] put(PCEPObject obj) {
97                 if (!(obj instanceof PCEPOpenObject))
98                         throw new IllegalArgumentException("Wrong instance of PCEPObject. Passed " + obj.getClass() + ". Needed PCEPOpenObject.");
99
100                 final PCEPOpenObject openObj = (PCEPOpenObject) obj;
101
102                 final byte versionFlagMF = (byte) (PCEPOpenObject.PCEP_VERSION << (Byte.SIZE - VERSION_SF_LENGTH));
103
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)];
106
107                 // serialize version_flags multi-field
108                 bytes[VER_FLAGS_MF_OFFSET] = versionFlagMF;
109
110                 // serialize keepalive
111                 bytes[KEEPALIVE_F_OFFSET] = (byte) openObj.getKeepAliveTimerValue();
112
113                 // serialize dead timer
114                 bytes[DEAD_TIMER_OFFSET] = (byte) openObj.getDeadTimerValue();
115
116                 // serialize SID
117                 bytes[SID_F_OFFSET] = (byte) openObj.getSessionId();
118
119                 // serialize tlvs
120                 ByteArray.copyWhole(tlvs, bytes, TLVS_OFFSET);
121
122                 return bytes;
123         }
124 }