All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.brightsparklabs.asanti.AsantiCli Maven / Gradle / Ivy

The newest version!
/*
 * Maintained by brightSPARK Labs.
 * www.brightsparklabs.com
 *
 * Refer to LICENSE at repository root for license details.
 */

package com.brightsparklabs.asanti;

import com.brightsparklabs.asanti.common.OperationResult;
import com.brightsparklabs.asanti.exception.DecodeException;
import com.brightsparklabs.asanti.model.data.AsantiAsnData;
import com.brightsparklabs.asanti.model.data.RawAsnData;
import com.brightsparklabs.asanti.model.schema.AsnSchema;
import com.brightsparklabs.asanti.model.schema.DecodedTag;
import com.brightsparklabs.asanti.model.schema.Decoder;
import com.brightsparklabs.asanti.reader.AsnSchemaReader;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Ordering;
import com.google.common.io.BaseEncoding;
import com.google.common.io.ByteSource;
import com.google.common.io.CharSource;
import com.google.common.io.Files;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import org.apache.commons.cli.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Main class as an example of how to use the library.
 *
 * @author brightSPARK Labs
 */
public class AsantiCli {
    // -------------------------------------------------------------------------
    // CONSTANTS
    // -------------------------------------------------------------------------

    /** constant to use to add new lines to output */
    private static final String NEW_LINE = System.lineSeparator();

    // -------------------------------------------------------------------------
    // CLASS VARIABLES
    // -------------------------------------------------------------------------

    /** class logger */
    private static final Logger logger = LoggerFactory.getLogger(AsantiCli.class);

    // -------------------------------------------------------------------------
    // PUBLIC METHODS
    // -------------------------------------------------------------------------

    /**
     * Entry point to the application.
     *
     * @param args command line arguments
     */
    public static void main(final String[] args) {
        try {
            Options options = getOptions();
            CommandLineParser parser = new DefaultParser();
            final CommandLine cmdLine = parser.parse(options, args);
            validateCommandLine(cmdLine);

            switch (cmdLine.getArgs().length) {
                case 1:
                    final String filename = cmdLine.getArgs()[0];
                    final File file = new File(filename);

                    if (filename.endsWith(".asn")) {
                        testReadingAsnFile(file);
                    } else {
                        testReadingBerFile(file);
                    }
                    break;

                case 2:
                    throw new ParseException("Top level type name not supplied");

                case 3:
                    {
                        final String asnFilename =
                                cmdLine.getArgs()[0].endsWith(".asn")
                                        ? cmdLine.getArgs()[0]
                                        : cmdLine.getArgs()[1];
                        final String berFilename =
                                cmdLine.getArgs()[0].endsWith(".asn")
                                        ? cmdLine.getArgs()[1]
                                        : cmdLine.getArgs()[0];
                        final String topLevelType = cmdLine.getArgs()[2];
                        final File asnFile = new File(asnFilename);
                        final File berFile = new File(berFilename);
                        // Load the schema once, and use it for all data files.
                        final CharSource schemaSource = Files.asCharSource(asnFile, Charsets.UTF_8);
                        final AsnSchema asnSchema = AsnSchemaReader.read(schemaSource);
                        handleDataFile(berFile, asnSchema, topLevelType);
                    }
                    break;

                default:
                    throw new ParseException(
                            "No ASN Schema (.asn) or ASN Data (.ber) file supplied");
            }
        } catch (final IOException ex) {
            logger.error("Could not parse file", ex);
            System.exit(1);
        } catch (final ParseException e) {
            printUsage(e.getMessage());
            System.exit(1);
        }
    }

    // -------------------------------------------------------------------------
    // PRIVATE METHODS
    // -------------------------------------------------------------------------

    /**
     * Handle the loading of a single data (ber) file against the provided schema This will not
     * propagate exceptions, will only log them.
     *
     * @param berFile ASN.1 BER binary file to decode
     * @param asnSchema schema to decode against
     * @param topLevelType top level type in the schema to decode objects as
     */
    private static void loadDataFile(
            final File berFile, final AsnSchema asnSchema, final String topLevelType) {
        try {

            logger.info("Loading file: " + berFile.getCanonicalPath());

            final ByteSource byteSource = Files.asByteSource(berFile);
            final ImmutableList pdus =
                    Asanti.decodeAsnData(byteSource, asnSchema, topLevelType);
            for (int i = 0; i < pdus.size(); i++) {

                logger.info("Parsing PDU[{}]", i);
                final AsantiAsnData pdu = pdus.get(i);
                for (final String tag : pdu.getTags()) {
                    try {
                        logger.info(
                                "\t{} => {} as {}",
                                tag,
                                pdu.getPrintableString(tag).get(),
                                pdu.getType(tag).get().getBuiltinType());
                    } catch (final DecodeException e) {
                        logger.info(
                                "\t{} => {} as {} (as HexString because {})",
                                tag,
                                pdu.getHexString(tag).get(),
                                pdu.getType(tag).get().getBuiltinType(),
                                e.getMessage());
                    }
                }
                for (final String tag : pdu.getUnmappedTags()) {
                    logger.info("\t?{} => {}", tag, pdu.getHexString(tag));
                }
            }
        } catch (final Exception e) {
            logger.error("Exception loading data file: " + e.getMessage());
        }
    }

    /**
     * This function will take a schema file and run it against the data file(s) passed. If dataFile
     * is a directory then it will load all files in the directory (against the schema), and recurse
     * directories. This will attempt to ignore/skip files that are not ASN.1 BER files. This will
     * not propagate exceptions, will only log them.
     *
     * @param rootFile either a directory or ASN.1 BER binary file to decode
     * @param asnSchema schema to decode against
     * @param topLevelType the name of the top level
     */
    private static void handleDataFile(
            final File rootFile, final AsnSchema asnSchema, final String topLevelType) {
        for (final File file : Files.fileTraverser().depthFirstPreOrder(rootFile)) {
            try {
                if (!file.isDirectory()) {
                    final String name = file.getCanonicalPath();

                    // I don't really know what the 'right' file extensions are, so let's just rule
                    // out
                    // some of the ones that we have come across that are not BER files!
                    if (!name.toLowerCase().endsWith(".txt") //
                            && !name.toLowerCase().endsWith(".jpg") //
                            && !name.toLowerCase().endsWith(".bmp") //
                            && !name.toLowerCase().endsWith(".asn") //
                            && !name.toLowerCase().endsWith(".zip") //
                            && !name.toLowerCase().endsWith(".wav") //
                            && !name.toLowerCase().endsWith(".pcap") //
                            && !name.toLowerCase().endsWith(".rtp") //
                            && !name.toLowerCase().endsWith(".csv") //
                            && !name.toLowerCase().endsWith(".xlsx") //
                            && !name.toLowerCase().endsWith(".xls")) {
                        loadDataFile(file, asnSchema, topLevelType);
                    } else {
                        logger.debug("Ignoring file: " + name);
                    }
                }
            } catch (final Exception e) {
                logger.error("Exception: " + e.getMessage());
            }
        }
    }

    /**
     * Test parsing an ASN.1 schema file
     *
     * @param asnFile file to parse
     * @throws IOException if any errors occur while parsing
     */
    private static void testReadingAsnFile(final File asnFile) throws IOException {
        final CharSource schemaSource = Files.asCharSource(asnFile, Charsets.UTF_8);
        final AsnSchema asnSchema = AsnSchemaReader.read(schemaSource);

        logger.info("User testing:");
        final BufferedReader reader =
                new BufferedReader(new InputStreamReader(System.in, Charsets.UTF_8));
        while (true) {
            System.out.print("\tEnter raw tag: ");
            final String rawTag = reader.readLine();

            ImmutableSet> results =
                    Decoder.getDecodedTags(ImmutableList.of(rawTag), "PS-PDU", asnSchema);
            OperationResult result = results.iterator().next();
            logger.info(
                    "\t{}:\t decode {} => {}",
                    result.wasSuccessful() ? "PASS" : "FAIL",
                    rawTag,
                    result.getOutput().getTag());
        }
    }

    /**
     * Test parsing a BER file
     *
     * @param berFile file to parse
     * @throws IOException if any errors occur while parsing
     */
    private static void testReadingBerFile(final File berFile) throws IOException {
        final ByteSource byteSource = Files.asByteSource(berFile);
        final ImmutableList data = Asanti.readAsnBerData(byteSource);
        int count = 0;
        for (final RawAsnData rawAsnData : data) {
            logger.info("PDU[" + count + "]");
            final Map tagsData = rawAsnData.getBytes();

            for (final String tag : Ordering.natural().immutableSortedCopy(tagsData.keySet())) {
                logger.info("\t {}: 0x{}", tag, BaseEncoding.base16().encode(tagsData.get(tag)));
            }
            count++;
        }
    }

    /**
     * Returns the Command Line Options for this application
     *
     * @return the Command Line Options for this application
     */
    private static Options getOptions() {
        return new Options().addOption("h", "help", false, "Print out help");
    }

    /**
     * Performs application validation against the provided command line. If the validation fails
     * then an appropriate exception will be thrown (ParseException or subclasses)
     *
     * @param cmdLine the command line passes to main
     * @throws ParseException if there are issues with the options or arguments
     */
    private static void validateCommandLine(final CommandLine cmdLine) throws ParseException {
        if (cmdLine.hasOption("h")) {
            throw new ParseException("");
        }

        if (cmdLine.getArgs().length != 1 && cmdLine.getArgs().length != 3) {
            throw new MissingArgumentException("Must specify 1 or 3 arguments");
        }

        // All good!
    }

    /**
     * Prints the usage message
     *
     * @param footerMessage adds to the footer of the message, useful for specifying known issues
     *     with usage.
     */
    private static void printUsage(final String footerMessage) {
        final String callPattern =
                "USAGE: asanti [options] "
                        + NEW_LINE
                        + "    asanti [options] "
                        + NEW_LINE
                        + "    asanti [options]   "
                        + NEW_LINE
                        + NEW_LINE
                        + "Where:"
                        + NEW_LINE
                        + "    asn_schema_file        the ASN.1 schema file to parse (must end in '.asn')"
                        + NEW_LINE
                        + "    asn_ber_file           the ASN.1 BER file to parse (must end in '.ber')"
                        + NEW_LINE
                        + "    top_level_type         the name of the top level type in the schema file";

        final HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp(callPattern, "Options:", getOptions(), NEW_LINE + footerMessage);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy