d77386a272213c403ba850b220e224ca7cc22222
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / PCEPMessageHeader.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.Arrays;
11
12 import org.opendaylight.protocol.framework.ProtocolMessageHeader;
13 import org.opendaylight.protocol.util.ByteArray;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 import com.google.common.primitives.UnsignedBytes;
18
19 /**
20  * Header parser for {@link org.opendaylight.protocol.pcep.PCEPMessage PCEPMessage}
21  */
22 public final class PCEPMessageHeader implements ProtocolMessageHeader {
23
24         public static final Logger logger = LoggerFactory.getLogger(PCEPMessageHeader.class);
25
26         /*
27          * lengths of fields in bytes
28          */
29         private static final int VER_FLAGS_MF_LENGTH = 1;
30         private static final int TYPE_F_LENGTH = 1;
31         private static final int LENGTH_F_LENGTH = 2;
32
33         /*
34          * lengths of subfields inside multi-field in bits
35          */
36         private static final int VERSION_SF_LENGTH = 3;
37
38         /*
39          * offsets of field in bytes
40          */
41         private static final int VER_FLAGS_MF_OFFSET = 0;
42         private static final int TYPE_F_OFFSET = VER_FLAGS_MF_LENGTH + VER_FLAGS_MF_OFFSET;
43         private static final int LENGTH_F_OFFSET = TYPE_F_LENGTH + TYPE_F_OFFSET;
44
45         /*
46          * offsets of subfields inside multi-filed in bits
47          */
48
49         private static final int VERSION_SF_OFFSET = 0;
50
51         /*
52          * COMMON HEADER LENGTH
53          */
54         public static final int COMMON_HEADER_LENGTH = VER_FLAGS_MF_LENGTH + TYPE_F_LENGTH + LENGTH_F_LENGTH;
55
56         private final int type;
57         private final int length;
58         private final int version;
59
60         public PCEPMessageHeader(final int type, final int length, final int version) {
61                 this.type = type;
62                 this.length = length;
63                 this.version = version;
64         }
65
66         public static PCEPMessageHeader fromBytes(final byte[] bytes) {
67                 if (bytes == null) {
68                         throw new IllegalArgumentException("Array of bytes is mandatory");
69                 }
70
71                 logger.trace("Attempt to parse message header: {}", ByteArray.bytesToHexString(bytes));
72
73                 if (bytes.length < COMMON_HEADER_LENGTH) {
74                         throw new IllegalArgumentException("Too few bytes in passed array. Passed: " + bytes.length + "; Expected: >= " + COMMON_HEADER_LENGTH + ".");
75                 }
76
77                 final int type = UnsignedBytes.toInt(bytes[TYPE_F_OFFSET]);
78
79                 final int length = ByteArray.bytesToInt(Arrays.copyOfRange(bytes,
80                                 LENGTH_F_OFFSET, LENGTH_F_OFFSET + LENGTH_F_LENGTH));
81
82                 final int version = ByteArray.copyBitsRange(bytes[VER_FLAGS_MF_OFFSET], VERSION_SF_OFFSET, VERSION_SF_LENGTH);
83
84                 final PCEPMessageHeader ret = new PCEPMessageHeader(type, length, version);
85
86                 logger.trace("Message header was parsed. {}", ret);
87                 return ret;
88         }
89
90         public byte[] toBytes() {
91                 final byte[] retBytes = new byte[COMMON_HEADER_LENGTH];
92
93                 // msgVer_Flag
94                 retBytes[VER_FLAGS_MF_OFFSET] = (byte) (this.version << (Byte.SIZE - VERSION_SF_LENGTH));
95
96                 // msgType
97                 retBytes[TYPE_F_OFFSET] = (byte) this.type;
98
99                 // msgLength
100                 System.arraycopy(ByteArray.intToBytes(this.length), Integer.SIZE / Byte.SIZE - LENGTH_F_LENGTH, retBytes, LENGTH_F_OFFSET, LENGTH_F_LENGTH);
101
102                 return retBytes;
103         }
104
105         public int getLength() {
106                 return this.length;
107         }
108
109         public int getVersion() {
110                 return this.version;
111         }
112
113         public int getType() {
114                 return this.type;
115         }
116
117         @Override
118         public String toString() {
119                 final StringBuilder builder = new StringBuilder();
120                 builder.append("PCEPMessageHeader [type=");
121                 builder.append(this.type);
122                 builder.append(", length=");
123                 builder.append(this.length);
124                 builder.append(", version=");
125                 builder.append(this.version);
126                 builder.append("]");
127                 return builder.toString();
128         }
129 }