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

pcap.jdk7.internal.DefaultDumper Maven / Gradle / Ivy

/*
 * Copyright (c) 2020-2021 Pcap Project
 * SPDX-License-Identifier: MIT OR Apache-2.0
 */
package pcap.jdk7.internal;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import pcap.spi.Dumper;
import pcap.spi.PacketBuffer;
import pcap.spi.PacketHeader;

class DefaultDumper implements Dumper {

  static final Set> REFS =
      Collections.synchronizedSet(new HashSet>());
  static final ReferenceQueue RQ = new ReferenceQueue();
  final DumperReference reference;
  private final Pointer pointer;
  private final Pointer hdrPtr; // for copying header

  DefaultDumper(Pointer pointer) {
    this.pointer = pointer;
    long address = Native.malloc(DefaultPacketHeader.SIZEOF);
    this.hdrPtr = new Pointer(address);
    this.reference = new DumperReference(address, this, RQ);
    REFS.add(reference);
    DumperReference ref;
    while ((ref = (DumperReference) RQ.poll()) != null) {
      freeIfPossible(ref);
    }
  }

  static void freeIfPossible(DumperReference ref) {
    if (ref.address > 0) {
      Native.free(ref.address);
      ref.address = 0L;
      DefaultDumper.REFS.remove(ref);
    }
  }

  static void setNativeLong(Pointer ptr, long offset, long value, int longSize) {
    if (longSize == 8) {
      ptr.setLong(offset, value);
    } else {
      ptr.setInt(offset, (int) value);
    }
  }

  @Override
  public void dump(PacketHeader header, PacketBuffer buffer) {
    Utils.requireNonNull(header, "header: null (expected: header != null).");
    Utils.requireNonNull(buffer, "buffer: null (expected: buffer != null).");
    if (buffer.capacity() <= 0) {
      throw new IllegalArgumentException(
          String.format(
              "buffer.capacity: %d (expected: buffer.capacity(%d) > 0)",
              buffer.capacity(), buffer.capacity()));
    }
    if (buffer.readableBytes() < header.length()) {
      throw new IllegalArgumentException(
          String.format(
              "buffer.readableBytes(): %d (expected: buffer.readableBytes(%d) >= header.length(%d))",
              buffer.readableBytes(), buffer.readableBytes(), header.length()));
    }
    DefaultPacketBuffer packetBuffer = (DefaultPacketBuffer) buffer;
    setNativeLong(
        hdrPtr, DefaultTimestamp.TV_SEC_OFFSET, header.timestamp().second(), Native.LONG_SIZE);
    setNativeLong(
        hdrPtr,
        DefaultTimestamp.TV_USEC_OFFSET,
        header.timestamp().microSecond(),
        Native.LONG_SIZE);
    hdrPtr.setInt(DefaultPacketHeader.CAPLEN_OFFSET, header.captureLength());
    hdrPtr.setInt(DefaultPacketHeader.LEN_OFFSET, header.length());
    NativeMappings.pcap_dump(
        pointer, hdrPtr, packetBuffer.buffer.share(packetBuffer.readerIndex()));
  }

  @Override
  public long position() {
    return NativeMappings.PLATFORM_DEPENDENT.pcap_dump_ftell(pointer).longValue();
  }

  @Override
  public void flush() {
    NativeMappings.pcap_dump_flush(pointer);
  }

  @Override
  public void close() {
    NativeMappings.pcap_dump_close(pointer);
  }

  @Override
  public boolean equals(Object o) {
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    DefaultDumper that = (DefaultDumper) o;
    return Pointer.nativeValue(pointer) == Pointer.nativeValue(that.pointer);
  }

  @Override
  public int hashCode() {
    return Objects.hash(Pointer.nativeValue(pointer));
  }

  static final class DumperReference extends PhantomReference {

    long address;

    DumperReference(long address, DefaultDumper referent, ReferenceQueue q) {
      super(referent, q);
      this.address = address;
    }

    @Override
    public boolean equals(Object o) {
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      DumperReference that = (DumperReference) o;
      return hashCode() == that.hashCode();
    }

    @Override
    public int hashCode() {
      return Objects.hash(address);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy