com.exalttech.trex.util.TrafficProfile.java Source code

Java tutorial

Introduction

Here is the source code for com.exalttech.trex.util.TrafficProfile.java

Source

/**
 * *****************************************************************************
 * Copyright (c) 2016
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************
 */
package com.exalttech.trex.util;

import com.exalttech.trex.remote.models.profiles.Mode;
import com.exalttech.trex.remote.models.profiles.PacketInfo;
import com.exalttech.trex.remote.models.profiles.Profile;
import com.exalttech.trex.ui.views.models.TableProfileStream;
import com.exalttech.trex.util.files.FileManager;
import com.exalttech.trex.util.files.FileType;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import javafx.stage.Window;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.pcap4j.core.NotOpenException;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.Pcaps;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.IllegalRawDataException;
import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.TcpPacket;
import org.pcap4j.packet.UdpPacket;

/**
 *
 * @author GeorgeKh
 */
public class TrafficProfile {

    private static final Logger LOG = Logger.getLogger(TrafficProfile.class.getName());

    /**
     *
     */
    public TrafficProfile() {
        super();

    }

    /**
     *
     * @param packet
     * @return
     */
    public PacketInfo getPacketTypeText(Packet packet) {
        PacketInfo packetInfo = new PacketInfo();

        String packetType = "";
        // Default values for packet info
        packetInfo.setType("Unknown");
        packetInfo.setLength(packet.length());
        if (packet != null) {
            // EthernetPacket
            if (packet.get(EthernetPacket.class) != null) {
                packetType += "Ethernet/";
            }
            // IPPacket
            if (packet.get(IpV4Packet.class) != null) {
                packetType += "IPV4/";
            }
            // TCPPacket
            if (packet.get(TcpPacket.class) != null) {
                packetType += "TCP/";
            }
            // UDPPacket
            if (packet.get(UdpPacket.class) != null) {
                packetType += "UDP";
            }
            if (packetType.endsWith("/")) {
                packetType = packetType.substring(0, packetType.length() - 1);
            }
            packetInfo.setType(packetType);
        }
        return packetInfo;
    }

    /**
     *
     * @param packetBinary
     * @return
     */
    public PacketInfo getPacketInfo(String packetBinary) {

        PacketInfo packetInfo = null;

        try {
            byte[] pkt = Base64.decodeBase64(packetBinary);
            Packet packet = EthernetPacket.newPacket(pkt, 0, pkt.length);
            packetInfo = getPacketTypeText(packet);
        } catch (IllegalRawDataException ex) {
            LOG.error("Error reading packet info", ex);
        }

        return packetInfo;

    }

    /**
     * @param binaryFile
     * @return Encodes the bytes array of a PCAP File using Base64
     */
    public String encodePcapFile(String binaryFile) {

        try {
            PcapHandle handle = Pcaps.openOffline(binaryFile);
            Packet packet = handle.getNextPacketEx();
            handle.close();
            byte[] pkt = packet.getRawData();
            byte[] bytesEncoded = Base64.encodeBase64(pkt);

            return new String(bytesEncoded);
        } catch (IOException | PcapNativeException | TimeoutException | NotOpenException ex) {
            LOG.error("Error encoding pcap file", ex);
            return binaryFile;
        }

    }

    /**
     * @param binaryPacket
     * @throws java.io.IOException
     * @
     * @return decodes the bytes array of a PCAP File using Base64
     */
    public File decodePcapBinary(String binaryPacket) throws IOException {

        byte[] decodedBytes = Base64.decodeBase64(binaryPacket);
        File pcapFile = File.createTempFile("temp-file-name", ".pcap");
        FileUtils.writeByteArrayToFile(pcapFile, decodedBytes);
        return pcapFile;
    }

    /**
     *
     * @param hexPacket
     * @return Converts a Hex packet to a base64 encoded packet.
     */
    public String encodeBinaryFromHexString(String hexPacket) {
        if (!Util.isNullOrEmpty(hexPacket)) {
            byte[] rawData = DatatypeConverter.parseHexBinary(hexPacket);
            return new String(Base64.encodeBase64(rawData));
        }
        return null;
    }

    /**
     * @param yamlFile File containing the Traffic Profile Yaml.
     * @return parsed Yaml file
     * @throws java.io.IOException
     */
    public Profile[] getTrafficProfile(File yamlFile) throws IOException {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        Profile[] trafficProfileArray = mapper.readValue(yamlFile, Profile[].class);
        int i = 0;
        for (Profile profile : trafficProfileArray) {
            Map<String, Object> streamAdditionalProperties = profile.getStream().getAdditionalProperties();
            if (streamAdditionalProperties.containsKey("vm")) {
                profile.getStream().setVmRaw(streamAdditionalProperties.get("vm").toString());
            }
            if (streamAdditionalProperties.containsKey("rx_stats")) {
                profile.getStream().setRxStatsRaw(streamAdditionalProperties.get("rx_stats").toString());
            }
            // Check the Binary is in the Yaml File
            if (profile.getStream().getPacket().getBinary() == null) {
                String absolutePath = yamlFile.getAbsolutePath();
                String filePath = absolutePath.substring(0, absolutePath.lastIndexOf(File.separator));
                String pacpFile = profile.getStream().getPacket().getPcap();
                String encodedPcap = encodePcapFile(filePath + File.separator + pacpFile);
                profile.getStream().getPacket().setBinary(encodedPcap);
            }
            profile.getStream().getPacket().setPcap(null);

            if (profile.getName() == null) {
                profile.setName("Stream" + i++);
            }

        }
        return trafficProfileArray;
    }

    /**
     * Convert profiles to equivalent tableProfile data
     *
     * @param profilesList
     * @return
     */
    public List<TableProfileStream> convertProfilesToTableData(Profile[] profilesList) {
        List<TableProfileStream> tableData = new ArrayList<>();
        for (int index = 0; index < profilesList.length; index++) {
            Profile p = profilesList[index];
            TableProfileStream stream = new TableProfileStream();
            Mode modeYaml = p.getStream().getMode();
            stream.setIndex(String.valueOf(index + 1));
            stream.setEnabled(p.getStream().isEnabled());
            stream.setName(p.getName());
            stream.setMode(modeYaml.getType());
            stream.setRate(String.valueOf(modeYaml.getPps()));
            stream.setNextStream(getNextStreamValue(p.getNext()));
            String packetBinary = p.getStream().getPacket().getBinary();
            stream.setPcapBinary(packetBinary);
            PacketInfo packetInfo = getPacketInfo(packetBinary);
            stream.setLength(String.valueOf(packetInfo.getLength() + Constants.EXTRA_BYTE));
            stream.setPacketType(packetInfo.getType());
            tableData.add(stream);
        }

        return tableData;
    }

    /**
     * @param trafficProfileArray
     * @param portID
     * @param handler
     * @return returns a formatted JSON Array of Streams for a given port
     * @throws Exception
     *
     */
    public String convertTrafficProfileToJson(Profile[] trafficProfileArray, int portID, String handler)
            throws Exception {
        Profile[] preparedTrafficProfile = prepareTrafficProfile(trafficProfileArray, portID, handler);

        ObjectMapper mapper = new ObjectMapper();
        String jsonString = mapper.writeValueAsString(preparedTrafficProfile);
        return Util.toPrettyFormat(jsonString);

    }

    /**
     * @param trafficProfileArray
     *
     * @return Converts Traffic Profile to Yaml String
     * @throws JsonProcessingException
     *
     */
    public String convertTrafficProfileToYaml(Profile[] trafficProfileArray) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        return mapper.writeValueAsString(trafficProfileArray);
    }

    /**
     * @param trafficProfileArray
     * @param fileName
     *
     * @return Converts Traffic Profile to Yaml String
     * @throws JsonProcessingException
     *
     */
    public File convertTrafficProfileToYamlFile(Profile[] trafficProfileArray, String fileName) throws IOException {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        String localFileName = FileManager.getProfilesFilePath() + fileName;
        File yamlFile = new File(localFileName);
        mapper.writeValue(yamlFile, trafficProfileArray);
        return yamlFile;
    }

    private String getNextStreamValue(String nextStream) {

        if (nextStream == null || "-1".equals(nextStream)) {
            return "None";
        }
        return nextStream;
    }

    /**
     *
     * @param trafficProfileArray
     * @param portID
     * @param handler
     * @return
     * @throws java.lang.Exception
     */
    public Profile[] prepareTrafficProfile(Profile[] trafficProfileArray, int portID, String handler)
            throws Exception {
        Map<String, Integer> mapStreamToInteger = convertStreamNameToInteger(trafficProfileArray);

        ObjectMapper mapper = new ObjectMapper();
        String profileJsonString = mapper.writeValueAsString(trafficProfileArray);
        Profile[] updatedProfileArray = mapper.readValue(profileJsonString, Profile[].class);
        for (int i = 0; i < updatedProfileArray.length; i++) {

            Profile trafficProfile = updatedProfileArray[i];
            Profile originalProfile = trafficProfileArray[i];
            trafficProfile.setStreamId(mapStreamToInteger.get(trafficProfile.getName()));
            if (!"-1".equals(trafficProfile.getNext())) {
                trafficProfile.getStream().setNextStreamId(mapStreamToInteger.get(trafficProfile.getNext()));
            }

            trafficProfile.setName(null);
            trafficProfile.setNext(null);
            trafficProfile.getStream().getPacket().setPcap(null);
            String vm = (!originalProfile.getStream().getVmRaw().isEmpty()
                    && !"[]".equals(originalProfile.getStream().getVmRaw()))
                            ? originalProfile.getStream().getVmRaw()
                            : "{\n" + "                    \"instructions\": [],\n"
                                    + "                    \"split_by_var\": \"\"\n" + "                }";
            String rx = (!originalProfile.getStream().getRxStatsRaw().isEmpty()
                    && !"[]".equals(originalProfile.getStream().getRxStatsRaw()))
                            ? originalProfile.getStream().getRxStatsRaw()
                            : "{\n" + "                    \"enabled\": false\n" + "                }";
            trafficProfile.getStream().setVmRaw(vm);
            trafficProfile.getStream().setRxStatsRaw(rx);

            trafficProfile.setHandler(handler);
            trafficProfile.setPortId(portID);
            trafficProfile.getStream().getMode().getRate()
                    .setValue((int) trafficProfile.getStream().getMode().getPps());
            updatedProfileArray[i] = trafficProfile;

        }
        return updatedProfileArray;
    }

    /**
     * Convert stream name to integer
     *
     * @param trafficProfileArray
     * @return
     */
    public Map<String, Integer> convertStreamNameToInteger(Profile[] trafficProfileArray) {
        HashMap<String, Integer> streamNameMap = new HashMap<>();
        int streamID = 0;
        for (Profile profile : trafficProfileArray) {
            if (!streamNameMap.containsKey(profile.getName())) {
                streamNameMap.put(profile.getName(), streamID++);
            }
        }
        return streamNameMap;
    }

    /**
     *
     * @param owner
     * @param profiles
     * @param fileName
     */
    public void exportProfileToYaml(Window owner, Profile[] profiles, String fileName) {
        try {
            String data = getProfileYamlContent(profiles);
            FileManager.exportFile("Save Yaml File", fileName, data, owner, FileType.YAML);
        } catch (IOException ex) {
            LOG.error("Error during generate YAML file", ex);
        }
    }

    /**
     * Return cleaned profile yaml content
     * @param profiles
     * @return
     * @throws JsonProcessingException 
     */
    public String getProfileYamlContent(Profile[] profiles) throws JsonProcessingException {
        String data = convertTrafficProfileToYaml(profiles);

        // Clean up Yaml file
        data = data.replace("next: \"-1\"", "");
        data = data.replace("next_stream_id: -1", "");
        return data;
    }
}