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

org.pcap4j.packet.Dot11AbstractSupportedRatesElement Maven / Gradle / Ivy

The newest version!
/*_##########################################################################
  _##
  _##  Copyright (C) 2016  Pcap4J.org
  _##
  _##########################################################################
*/

package org.pcap4j.packet;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.pcap4j.packet.namednumber.Dot11BssMembershipSelector;
import org.pcap4j.packet.namednumber.Dot11InformationElementId;

/**
 * IEEE802.11 abstract Supported Rates element
 *
 * @see IEEE802.11
 * @author Kaito Yamada
 * @since pcap4j 1.7.0
 */
public abstract class Dot11AbstractSupportedRatesElement extends Dot11InformationElement {

  /** */
  private static final long serialVersionUID = -1751480012950433980L;

  private final List rates;
  private final List bssMembershipSelectors;
  private final List ratesAndBssMembershipSelectors;

  /**
   * @param rawData rawData
   * @param offset offset
   * @param length length
   * @param id id
   * @throws IllegalRawDataException if parsing the raw data fails.
   */
  protected Dot11AbstractSupportedRatesElement(
      byte[] rawData, int offset, int length, Dot11InformationElementId id)
      throws IllegalRawDataException {
    super(rawData, offset, length, id);

    this.rates = new ArrayList();
    this.bssMembershipSelectors = new ArrayList();
    this.ratesAndBssMembershipSelectors = new ArrayList();
    int infoLen = getLengthAsInt();
    for (int i = 0; i < infoLen; i++) {
      byte next = rawData[offset + 2 + i];
      boolean basic = (next & 0x80) != 0;
      byte val = (byte) (next & 0x7F);
      if (Dot11BssMembershipSelector.isRegistered(val)) {
        BssMembershipSelector sel =
            new BssMembershipSelector(basic, Dot11BssMembershipSelector.getInstance(val));
        bssMembershipSelectors.add(sel);
        ratesAndBssMembershipSelectors.add(sel);
      } else {
        Rate rate = new Rate(basic, val);
        rates.add(rate);
        ratesAndBssMembershipSelectors.add(rate);
      }
    }
  }

  /** @param builder builder */
  protected Dot11AbstractSupportedRatesElement(Builder builder) {
    super(builder);

    if (builder.ratesAndBssMembershipSelectors.size() > 255) {
      throw new IllegalArgumentException(
          "Too long ratesAndBssMembershipSelectors: " + builder.ratesAndBssMembershipSelectors);
    }

    this.rates = new ArrayList();
    this.bssMembershipSelectors = new ArrayList();
    for (Datum obj : builder.ratesAndBssMembershipSelectors) {
      if (obj instanceof Rate) {
        rates.add((Rate) obj);
      } else if (obj instanceof BssMembershipSelector) {
        bssMembershipSelectors.add((BssMembershipSelector) obj);
      } else {
        throw new IllegalArgumentException(
            "An illegal object in builder.ratesAndBssMembershipSelectors: " + obj);
      }
    }
    this.ratesAndBssMembershipSelectors =
        new ArrayList(builder.ratesAndBssMembershipSelectors);
  }

  /** @return rates */
  public List getRates() {
    return new ArrayList(rates);
  }

  /** @return bssMembershipSelectors */
  public List getBssMembershipSelectors() {
    return new ArrayList(bssMembershipSelectors);
  }

  @Override
  public int length() {
    return 2 + ratesAndBssMembershipSelectors.size();
  }

  @Override
  public byte[] getRawData() {
    byte[] rawData = new byte[length()];
    rawData[0] = getElementId().value();
    rawData[1] = getLength();
    int i = 2;
    for (Datum datum : ratesAndBssMembershipSelectors) {
      rawData[i] = datum.getRawData();
      i++;
    }
    return rawData;
  }

  /** @return a new Builder object populated with this object's fields. */
  public abstract Builder getBuilder();

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = super.hashCode();
    result = prime * result + ratesAndBssMembershipSelectors.hashCode();
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (!super.equals(obj)) return false;
    Dot11AbstractSupportedRatesElement other = (Dot11AbstractSupportedRatesElement) obj;
    if (!ratesAndBssMembershipSelectors.equals(other.ratesAndBssMembershipSelectors)) return false;
    return true;
  }

  @Override
  public String toString() {
    return toString("");
  }

  /**
   * @param indent indent
   * @return the string representation of this object.
   */
  public String toString(String indent) {
    StringBuilder sb = new StringBuilder();
    String ls = System.getProperty("line.separator");

    sb.append(indent).append(getElementName()).append(":").append(ls);
    sb.append(indent).append("  Element ID: ").append(getElementId()).append(ls);
    sb.append(indent).append("  Length: ").append(getLengthAsInt()).append(" bytes").append(ls);
    for (Datum datum : ratesAndBssMembershipSelectors) {
      sb.append(indent).append("  ").append(datum).append(ls);
    }

    return sb.toString();
  }

  /** @return element name */
  protected abstract String getElementName();

  /**
   * @author Kaito Yamada
   * @since pcap4j 1.7.0
   */
  public interface Datum extends Serializable {

    /** @return the raw data. */
    public byte getRawData();
  }

  /**
   * @author Kaito Yamada
   * @since pcap4j 1.7.0
   */
  public static final class Rate implements Datum {

    /** */
    private static final long serialVersionUID = -3227287901080960330L;

    private final boolean basic;
    private final byte rate;

    /**
     * @param basic basic
     * @param rate rate
     */
    public Rate(boolean basic, byte rate) {
      if (rate < 0) {
        throw new IllegalArgumentException(
            "The rate must be between 0 to 127 but is actually: " + rate);
      }
      this.basic = basic;
      this.rate = rate;
    }

    /** @return true if this is a basic rate; false otherwise. */
    public boolean isBasic() {
      return basic;
    }

    /** @return rate */
    public byte getRate() {
      return rate;
    }

    /** @return rate in Mbit/sec. */
    public double getRateInMbitPerSec() {
      return rate * 0.5;
    }

    @Override
    public byte getRawData() {
      return (byte) (basic ? (0x80 | rate) : rate);
    }

    @Override
    public String toString() {
      StringBuilder sb =
          new StringBuilder(50)
              .append("Supported Rate: ")
              .append(getRateInMbitPerSec())
              .append(" Mbit/sec")
              .append(basic ? " (basic)" : " (non-basic)");
      return sb.toString();
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + (basic ? 1231 : 1237);
      result = prime * result + rate;
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (obj == null) return false;
      if (getClass() != obj.getClass()) return false;
      Rate other = (Rate) obj;
      if (basic != other.basic) return false;
      if (rate != other.rate) return false;
      return true;
    }
  }

  /**
   * @author Kaito Yamada
   * @since pcap4j 1.7.0
   */
  public static final class BssMembershipSelector implements Datum {

    /** */
    private static final long serialVersionUID = 5749787247631286263L;

    private final boolean basic;
    private final Dot11BssMembershipSelector selector;

    /**
     * @param basic basic
     * @param selector selector
     */
    public BssMembershipSelector(boolean basic, Dot11BssMembershipSelector selector) {
      if (selector == null) {
        throw new NullPointerException("selector is null.");
      }
      this.basic = basic;
      this.selector = selector;
    }

    /** @return true if this is a basic rate; false otherwise. */
    public boolean isBasic() {
      return basic;
    }

    /** @return selector */
    public Dot11BssMembershipSelector getSelector() {
      return selector;
    }

    @Override
    public byte getRawData() {
      byte sel = selector.value();
      return (byte) (basic ? (0x80 | sel) : sel);
    }

    @Override
    public String toString() {
      StringBuilder sb =
          new StringBuilder(50)
              .append("BSS Membership Selector: ")
              .append(selector)
              .append(basic ? " (basic)" : " (non-basic)");
      return sb.toString();
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + (basic ? 1231 : 1237);
      result = prime * result + selector.hashCode();
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (obj == null) return false;
      if (getClass() != obj.getClass()) return false;
      BssMembershipSelector other = (BssMembershipSelector) obj;
      if (basic != other.basic) return false;
      if (!selector.equals(other.selector)) return false;
      return true;
    }
  }

  /**
   * @author Kaito Yamada
   * @since pcap4j 1.7.0
   */
  public abstract static class Builder extends Dot11InformationElement.Builder {

    private List ratesAndBssMembershipSelectors;

    /** */
    public Builder() {}

    /** @param elem element. */
    protected Builder(Dot11AbstractSupportedRatesElement elem) {
      super(elem);
      this.ratesAndBssMembershipSelectors = elem.ratesAndBssMembershipSelectors;
    }

    /**
     * @param ratesAndBssMembershipSelectors ratesAndBssMembershipSelectors
     * @return this Builder object for method chaining.
     */
    public Builder ratesAndBssMembershipSelectors(List ratesAndBssMembershipSelectors) {
      this.ratesAndBssMembershipSelectors = ratesAndBssMembershipSelectors;
      return this;
    }

    /** Call me before build(). */
    protected void preBuild() {
      if (ratesAndBssMembershipSelectors == null) {
        throw new NullPointerException("ratesAndBssMembershipSelectors is null.");
      }
      if (getCorrectLengthAtBuild()) {
        length((byte) ratesAndBssMembershipSelectors.size());
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy