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;
16 import java.io.FileInputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.InputStreamReader;
20 import java.util.List;
21 import javax.annotation.concurrent.Immutable;
22 import org.apache.commons.codec.DecoderException;
23 import org.apache.commons.codec.binary.Hex;
24 import org.opendaylight.protocol.util.ByteArray;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
29 * Read text file, parse BGP messages. File can contain comments or other data. BGP messages are detected using 16 ff
30 * marker. New lines and spaces are ignored. Use {@link ByteArray#bytesToHexString(byte[])} for serializing bytes to
34 public final class HexDumpBGPFileParser {
35 private static final int MINIMAL_LENGTH = 19;
36 private static final Logger LOG = LoggerFactory.getLogger(HexDumpBGPFileParser.class);
37 private static final String FF_16 = Strings.repeat("FF", 16);
39 private HexDumpBGPFileParser() {
43 public static List<byte[]> parseMessages(final File file) throws IOException {
44 Preconditions.checkArgument(file != null, "Filename cannot be null");
45 return parseMessages(new FileInputStream(file));
48 public static List<byte[]> parseMessages(final InputStream is) throws IOException {
49 Preconditions.checkNotNull(is);
50 try (InputStreamReader isr = new InputStreamReader(is)) {
51 return parseMessages(CharStreams.toString(isr));
57 public static List<byte[]> parseMessages(final String c) {
58 final String content = clearWhiteSpaceToUpper(c);
61 final List<byte[]> messages = Lists.newLinkedList();
62 int idx = content.indexOf(FF_16, 0);
64 // next 2 bytes are length
65 final int lengthIdx = idx + 16 * 2;
66 final int messageIdx = lengthIdx + 4;
67 final String hexLength = content.substring(lengthIdx, messageIdx);
68 byte[] byteLength = null;
70 byteLength = Hex.decodeHex(hexLength.toCharArray());
71 } catch (final DecoderException e) {
72 throw new IllegalArgumentException("Failed to decode message length", e);
74 final int length = ByteArray.bytesToInt(byteLength);
75 final int messageEndIdx = idx + length * 2;
77 // Assert that message is longer than minimum 19(header.length == 19)
78 // If length in BGP message would be 0, loop would never end
79 Preconditions.checkArgument(length >= MINIMAL_LENGTH, "Invalid message at index " + idx + ", length atribute is lower than "
82 final String hexMessage = content.substring(idx, messageEndIdx);
83 byte[] message = null;
85 message = Hex.decodeHex(hexMessage.toCharArray());
86 } catch (final DecoderException e) {
87 throw new IllegalArgumentException("Failed to decode message body", e);
89 messages.add(message);
91 idx = content.indexOf(FF_16, idx);
93 LOG.info("Succesfully extracted {} messages", messages.size());
98 static String clearWhiteSpaceToUpper(final String line) {
99 return line.replaceAll("\\s", "").toUpperCase();