2 * Copyright (c) 2014 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
8 package org.opendaylight.controller.netconf.util.handler;
10 import java.nio.ByteBuffer;
11 import java.util.Arrays;
12 import java.util.List;
14 import org.opendaylight.controller.netconf.api.NetconfMessage;
15 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
16 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
17 import org.w3c.dom.Document;
19 import com.google.common.base.Charsets;
20 import com.google.common.collect.ImmutableList;
23 * Customized NetconfXMLToMessageDecoder that reads additional header with
24 * session metadata from
25 * {@link org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage}
26 * . Used by netconf server to retrieve information about session metadata.
28 public class NetconfXMLToHelloMessageDecoder extends NetconfXMLToMessageDecoder {
30 private static final List<byte[]> POSSIBLE_ENDS = ImmutableList.of(
31 new byte[] { ']', '\n' },
32 new byte[] { ']', '\r', '\n' });
33 private static final List<byte[]> POSSIBLE_STARTS = ImmutableList.of(
35 new byte[] { '\r', '\n', '[' },
36 new byte[] { '\n', '[' });
38 private String additionalHeaderCache;
41 protected byte[] preprocessMessageBytes(byte[] bytes) {
42 // Extract bytes containing header with additional metadata
44 if (startsWithAdditionalHeader(bytes)) {
45 // Auth information containing username, ip address... extracted for monitoring
46 int endOfAuthHeader = getAdditionalHeaderEndIndex(bytes);
47 if (endOfAuthHeader > -1) {
48 byte[] additionalHeaderBytes = Arrays.copyOfRange(bytes, 0, endOfAuthHeader + 2);
49 additionalHeaderCache = additionalHeaderToString(additionalHeaderBytes);
50 bytes = Arrays.copyOfRange(bytes, endOfAuthHeader + 2, bytes.length);
58 protected void cleanUpAfterDecode() {
59 additionalHeaderCache = null;
63 protected NetconfMessage buildNetconfMessage(Document doc) {
64 return new NetconfHelloMessage(doc, additionalHeaderCache == null ? null
65 : NetconfHelloMessageAdditionalHeader.fromString(additionalHeaderCache));
68 private int getAdditionalHeaderEndIndex(byte[] bytes) {
69 for (byte[] possibleEnd : POSSIBLE_ENDS) {
70 int idx = findByteSequence(bytes, possibleEnd);
80 private static int findByteSequence(final byte[] bytes, final byte[] sequence) {
81 if (bytes.length < sequence.length) {
82 throw new IllegalArgumentException("Sequence to be found is longer than the given byte array.");
84 if (bytes.length == sequence.length) {
85 if (Arrays.equals(bytes, sequence)) {
92 for (int i = 0; i < bytes.length; i++) {
93 if (bytes[i] == sequence[j]) {
95 if (j == sequence.length) {
105 private boolean startsWithAdditionalHeader(byte[] bytes) {
106 for (byte[] possibleStart : POSSIBLE_STARTS) {
108 for (byte b : possibleStart) {
112 if(i == possibleStart.length)
120 private String additionalHeaderToString(byte[] bytes) {
121 return Charsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString();