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
8 package org.opendaylight.protocol.bgp.util;
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Preconditions;
12 import com.google.common.base.Strings;
13 import com.google.common.collect.Lists;
14 import com.google.common.io.CharStreams;
17 import java.io.FileInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.InputStreamReader;
21 import java.util.List;
23 import javax.annotation.concurrent.Immutable;
25 import org.apache.commons.codec.DecoderException;
26 import org.apache.commons.codec.binary.Hex;
27 import org.opendaylight.protocol.util.ByteArray;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
32 * Read text file, parse BGP messages. File can contain comments or other data. BGP messages are detected using 16 ff
33 * marker. New lines and spaces are ignored. Use {@link ByteArray#bytesToHexString(byte[])} for serializing bytes to
37 public final class HexDumpBGPFileParser {
38 private static final int MINIMAL_LENGTH = 19;
39 private static final Logger LOG = LoggerFactory.getLogger(HexDumpBGPFileParser.class);
40 private static final String FF_16 = Strings.repeat("FF", 16);
42 private HexDumpBGPFileParser() {
46 public static List<byte[]> parseMessages(final File file) throws IOException {
47 Preconditions.checkArgument(file != null, "Filename cannot be null");
48 return parseMessages(new FileInputStream(file));
51 public static List<byte[]> parseMessages(final InputStream is) throws IOException {
52 Preconditions.checkNotNull(is);
53 try (InputStreamReader isr = new InputStreamReader(is)) {
54 return parseMessages(CharStreams.toString(isr));
60 public static List<byte[]> parseMessages(final String c) {
61 final String content = clearWhiteSpaceToUpper(c);
64 final List<byte[]> messages = Lists.newLinkedList();
65 int idx = content.indexOf(FF_16, 0);
67 // next 2 bytes are length
68 final int lengthIdx = idx + 16 * 2;
69 final int messageIdx = lengthIdx + 4;
70 final String hexLength = content.substring(lengthIdx, messageIdx);
71 byte[] byteLength = null;
73 byteLength = Hex.decodeHex(hexLength.toCharArray());
74 } catch (final DecoderException e) {
75 throw new IllegalArgumentException("Failed to decode message length", e);
77 final int length = ByteArray.bytesToInt(byteLength);
78 final int messageEndIdx = idx + length * 2;
80 // Assert that message is longer than minimum 19(header.length == 19)
81 // If length in BGP message would be 0, loop would never end
82 Preconditions.checkArgument(length >= MINIMAL_LENGTH, "Invalid message at index " + idx + ", length atribute is lower than "
85 final String hexMessage = content.substring(idx, messageEndIdx);
86 byte[] message = null;
88 message = Hex.decodeHex(hexMessage.toCharArray());
89 } catch (final DecoderException e) {
90 new IllegalArgumentException("Failed to decode message body", e);
92 messages.add(message);
94 idx = content.indexOf(FF_16, idx);
96 LOG.info("Succesfully extracted {} messages", messages.size());
101 static String clearWhiteSpaceToUpper(final String line) {
102 return line.replaceAll("\\s", "").toUpperCase();