<commit_before>package com.cisco.trex.stateless;

import com.cisco.trex.ClientBase;
import com.cisco.trex.stateless.exception.ServiceModeRequiredException;
import com.cisco.trex.stateless.exception.TRexConnectionException;
import com.cisco.trex.stateless.model.ApiVersionHandler;
import com.cisco.trex.stateless.model.Ipv6Node;
import com.cisco.trex.stateless.model.Port;
import com.cisco.trex.stateless.model.PortStatus;
import com.cisco.trex.stateless.model.Stream;
import com.cisco.trex.stateless.model.StreamMode;
import com.cisco.trex.stateless.model.StreamModeRate;
import com.cisco.trex.stateless.model.StreamVM;
import com.cisco.trex.stateless.model.TRexClientResult;
import com.cisco.trex.stateless.model.port.PortVlan;
import com.cisco.trex.stateless.model.stats.ActivePGIds;
import com.cisco.trex.stateless.model.stats.ActivePGIdsRPCResult;
import com.cisco.trex.stateless.model.stats.PGIdStatsRPCResult;
import com.cisco.trex.stateless.model.vm.VMInstruction;
import com.cisco.trex.util.Constants;
import com.cisco.trex.util.TRexClientUtil;
import com.cisco.trex.util.TRexServerMode;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.commons.lang3.StringUtils;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.Dot1qVlanTagPacket;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.IcmpV4CommonPacket;
import org.pcap4j.packet.IcmpV4EchoPacket;
import org.pcap4j.packet.IcmpV4EchoReplyPacket;
import org.pcap4j.packet.IllegalRawDataException;
import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.IpV4Rfc791Tos;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.ArpHardwareType;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.packet.namednumber.IcmpV4Code;
import org.pcap4j.packet.namednumber.IcmpV4Type;
import org.pcap4j.packet.namednumber.IpNumber;
import org.pcap4j.packet.namednumber.IpVersion;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.MacAddress;

/** TRex client for stateless traffic */
public class TRexClient extends ClientBase {

  private static final String TYPE = "type";
  private static final String STREAM = "stream";
  private static final String STREAM_ID = "stream_id";
  private static final EtherType QInQ =
      new EtherType((short) 0x88a8, "802.1Q Provider Bridge (Q-in-Q)");
  private static final int SESSON_ID = 123456789;

  TRexClient(TRexTransport transport, Set<String> supportedCommands) {
    // For unit testing
    this.transport = transport;
    this.host = "testHost";
    this.port = "testPort";
    this.userName = "testUser";
    supportedCmds.addAll(supportedCommands);
  }

  /**
   * constructor
   *
   * @param host
   * @param port
   * @param userName
   */
  public TRexClient(String host, String port, String userName) {
    this.host = host;
    this.port = port;
    this.userName = userName;
    supportedCmds.add("api_sync_v2");
    supportedCmds.add("get_supported_cmds");
    EtherType.register(QInQ);
  }

  @Override
  protected void serverAPISync() throws TRexConnectionException {
    LOGGER.info("Sync API with the TRex");

    Map<String, Object> parameters = new HashMap<>();
    parameters.put("name", "STL");
    int majorVersion = Constants.STL_API_VERSION_MAJOR;
    int minorVersion = Constants.STL_API_VERSION_MINOR;

    parameters.put("major", majorVersion);
    parameters.put("minor", minorVersion);

    TRexClientResult<ApiVersionHandler> result =
        callMethod("api_sync_v2", parameters, ApiVersionHandler.class);

    // Currently the TRex server has  the NBC  issue to uplift the  STL_API_VERSION_MAJOR version
    // This if-block is a temporary solution to support uplift the  STL_API_VERSION_MAJOR version ,
    // if the TRex server does not uplift its version ,the client will continue use the old api, if
    // the server uplift, the client will use the new api.
    if (!StringUtils.isBlank(result.getError()) && result.getError().contains("Version mismatch")) {
      String regrexString = "server: '([0-9]+)\\.([0-9]+)', client: '([0-9]+)\\.([0-9]+)'";
      Pattern pattern = Pattern.compile(regrexString);
      Matcher matcher = pattern.matcher(result.getError());
      if (matcher.find()) {
        majorVersion = Integer.parseInt(matcher.group(1));
        minorVersion = Integer.parseInt(matcher.group(2));
        if (!TRexClientUtil.isVersionCorrect(TRexServerMode.ASTF, majorVersion, minorVersion)) {
          new TRexConnectionException(
              "Unable to connect to TRex server. Required API version is "
                  + majorVersion
                  + "."
                  + minorVersion);
        }
        parameters.put("major", majorVersion);
        parameters.put("minor", minorVersion);
        result = callMethod("api_sync_v2", parameters, ApiVersionHandler.class);
      }
    }

    if (result.get() == null) {
      TRexConnectionException e =
          new TRexConnectionException(
              MessageFormat.format(
                  "Unable to connect to TRex server. Required API version is {0}.{1}. Error: {2}",
                  majorVersion, minorVersion, result.getError()));
      LOGGER.error("Unable to sync client with TRex server due to: API_H is null.", e.getMessage());
      throw e;
    }
    apiH = result.get().getApiH();
    LOGGER.info("Received api_H: {}", apiH);
  }

  public PortStatus acquirePort(int portIndex, Boolean force) {
    if (!portHandlers.containsKey(portIndex)) {
      Map<String, Object> payload = createPayload(portIndex);<commit_msg>Uplift api version<commit_after>package com.cisco.trex.stateless;

import com.cisco.trex.ClientBase;
import com.cisco.trex.stateless.exception.ServiceModeRequiredException;
import com.cisco.trex.stateless.exception.TRexConnectionException;
import com.cisco.trex.stateless.model.ApiVersionHandler;
import com.cisco.trex.stateless.model.Ipv6Node;
import com.cisco.trex.stateless.model.Port;
import com.cisco.trex.stateless.model.PortStatus;
import com.cisco.trex.stateless.model.Stream;
import com.cisco.trex.stateless.model.StreamMode;
import com.cisco.trex.stateless.model.StreamModeRate;
import com.cisco.trex.stateless.model.StreamVM;
import com.cisco.trex.stateless.model.TRexClientResult;
import com.cisco.trex.stateless.model.port.PortVlan;
import com.cisco.trex.stateless.model.stats.ActivePGIds;
import com.cisco.trex.stateless.model.stats.ActivePGIdsRPCResult;
import com.cisco.trex.stateless.model.stats.PGIdStatsRPCResult;
import com.cisco.trex.stateless.model.vm.VMInstruction;
import com.cisco.trex.util.Constants;
import com.cisco.trex.util.TRexClientUtil;
import com.cisco.trex.util.TRexServerMode;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.commons.lang3.StringUtils;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.Dot1qVlanTagPacket;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.IcmpV4CommonPacket;
import org.pcap4j.packet.IcmpV4EchoPacket;
import org.pcap4j.packet.IcmpV4EchoReplyPacket;
import org.pcap4j.packet.IllegalRawDataException;
import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.IpV4Rfc791Tos;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.ArpHardwareType;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.packet.namednumber.IcmpV4Code;
import org.pcap4j.packet.namednumber.IcmpV4Type;
import org.pcap4j.packet.namednumber.IpNumber;
import org.pcap4j.packet.namednumber.IpVersion;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.MacAddress;

/** TRex client for stateless traffic */
public class TRexClient extends ClientBase {

  private static final String TYPE = "type";
  private static final String STREAM = "stream";
  private static final String STREAM_ID = "stream_id";
  private static final EtherType QInQ =
      new EtherType((short) 0x88a8, "802.1Q Provider Bridge (Q-in-Q)");
  private static final int SESSON_ID = 123456789;

  TRexClient(TRexTransport transport, Set<String> supportedCommands) {
    // For unit testing
    this.transport = transport;
    this.host = "testHost";
    this.port = "testPort";
    this.userName = "testUser";
    supportedCmds.addAll(supportedCommands);
  }

  /**
   * constructor
   *
   * @param host
   * @param port
   * @param userName
   */
  public TRexClient(String host, String port, String userName) {
    this.host = host;
    this.port = port;
    this.userName = userName;
    supportedCmds.add("api_sync_v2");
    supportedCmds.add("get_supported_cmds");
    EtherType.register(QInQ);
  }

  @Override
  protected void serverAPISync() throws TRexConnectionException {
    LOGGER.info("Sync API with the TRex");

    Map<String, Object> parameters = new HashMap<>();
    parameters.put("name", "STL");
    int majorVersion = Constants.STL_API_VERSION_MAJOR;
    int minorVersion = Constants.STL_API_VERSION_MINOR;

    parameters.put("major", majorVersion);
    parameters.put("minor", minorVersion);

    TRexClientResult<ApiVersionHandler> result =
        callMethod("api_sync_v2", parameters, ApiVersionHandler.class);

    // Currently the TRex server has  the NBC  issue to uplift the  STL_API_VERSION_MAJOR version
    // This if-block is a temporary solution to support uplift the  STL_API_VERSION_MAJOR version ,
    // if the TRex server does not uplift its version ,the client will continue use the old api, if
    // the server uplift, the client will use the new api.
    if (!StringUtils.isBlank(result.getError()) && result.getError().contains("Version mismatch")) {
      String regrexString = "server: '([0-9]+)\\.([0-9]+)', client: '([0-9]+)\\.([0-9]+)'";
      Pattern pattern = Pattern.compile(regrexString);
      Matcher matcher = pattern.matcher(result.getError());
      if (matcher.find()) {
        majorVersion = Integer.parseInt(matcher.group(1));
        minorVersion = Integer.parseInt(matcher.group(2));
        if (!TRexClientUtil.isVersionCorrect(TRexServerMode.STL, majorVersion, minorVersion)) {
          new TRexConnectionException(
              "Unable to connect to TRex server. Required API version is "
                  + majorVersion
                  + "."
                  + minorVersion);
        }
        parameters.put("major", majorVersion);
        parameters.put("minor", minorVersion);
        result = callMethod("api_sync_v2", parameters, ApiVersionHandler.class);
      }
    }

    if (result.get() == null) {
      TRexConnectionException e =
          new TRexConnectionException(
              MessageFormat.format(
                  "Unable to connect to TRex server. Required API version is {0}.{1}. Error: {2}",
                  majorVersion, minorVersion, result.getError()));
      LOGGER.error("Unable to sync client with TRex server due to: API_H is null.", e.getMessage());
      throw e;
    }
    apiH = result.get().getApiH();
    LOGGER.info("Received api_H: {}", apiH);
  }

  public PortStatus acquirePort(int portIndex, Boolean force) {
    if (!portHandlers.containsKey(portIndex)) {
      Map<String, Object> payload = createPayload(portIndex);
{'fraction_non_alphanumeric': 0.11270983213429256, 'fraction_numerical': 0.010871302957633893, 'mean_word_length': 4.1086157615353205, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1688613', 'n_tokens_mistral': 4063, 'n_tokens_neox': 4024, 'n_words': 811}