java.lang.Object
net.i2p.client.streaming.impl.PcapWriter
All Implemented Interfaces:
Closeable, Flushable, AutoCloseable

public class PcapWriterextends Object implements Closeable, Flushable
Write a standard pcap file with a "TCP" packet that can be analyzed with standard tools such as wireshark.

The source and dest "IP" and "port" are fake but are generated from the hashes of the Destinations and stream ID's, so they will be consistent. The local "IP" will always be of the form 127.0.x.y Initial IP for a conn will be 127.0.0.0 for the local and 0.0.0.0 for the remote.

Reference: http://wiki.wireshark.org/Development/LibpcapFileFormat

The Jpcap library was close to what I want, but it requires you to instantiate a "captor" before you can write a file, and it requires a native lib to do so, and even then, it only wants to read the file, not write it.

We even calculate a correct TCP header checksum to keep the tools happy. We don't, however, convert I2P-style sequence numbers, which count packets, to TCP-style byte counts. We don't track a lowest-acked-thru byte count atm, really.

We do represent the window size in bytes though, so that's real confusing.

This is designed to debug the streaming lib, but there are not log calls for every single packet - pings and pongs, and various odd cases where received packets are dropped, are not logged.

Yes we could dump it natively and write a wireshark dissector. That sounds hard. And we wouldn't get the TCP stream analysis built into the tools.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    private static class 
    Builder for TCP option blocks in the pcap output.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private final I2PAppContext
    The app context.
    private final OutputStream
    Stream the pcap records are written to.
    private final Log
    Logger for the pcap writer.
    private static final byte[]
    Big-endian pcap global header, see file format ref - 24 bytes.
    private static final byte[]
    First half of the fake IP header.
    private static final byte[]
    Second half of the fake IP header.
    private static final byte[]
    Dummy MAC addresses, IPv4 ethertype.
    private static final int
    Options - give our custom ones some mnemonics.
    private static final int
    Max # of streaming lib payload bytes to dump.
    private static final byte[]
    Placeholder address of our side.
    private static final byte
    Option marking the end of the options.
    private static final byte
    Option carrying the sender's port.
    private static final byte
    Option carrying the maximum segment size.
    private static final byte
    Option of the negative ack.
    private static final byte
    Option carrying our send delay.
    private static final byte
    Option of the ping request.
    private static final byte
    Option of the ping reply.
    private static final byte
    Option carrying our receive delay.
    private static final byte
    Option carrying the signature.
    private static final byte
    Option requesting the signature.
    private static final byte[]
    Placeholder address of an unknown peer.
  • Constructor Summary

    Constructors
    Constructor
    Description
    Creates a new PcapWriter that writes to the specified file in the log directory.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Closes the output stream, flushing any buffered data.
    void
    Flushes any buffered data to the underlying output stream.
    private static long
    Calculate the lowest sequence number that has been acked through.
    private static int
    update(int checksum, byte[] b)
    One's complement 2-byte checksum update.
    private static int
    update(int checksum, byte[] b, int len)
    One's complement 2-byte checksum update.
    void
    Write an outbound packet to the pcap file.
    void
    write(Packet pkt, Connection con)
    Write an inbound packet to the pcap file.
    private void
    wrt(Packet pkt, Connection con, boolean isInbound)
    Write a packet to the pcap file in the proper format.

    Methods inherited from class Object

    clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • FILE_HEADER

      private static final byte[] FILE_HEADER
      Big-endian pcap global header, see file format ref - 24 bytes.
    • MAC_HEADER

      private static final byte[] MAC_HEADER
      Dummy MAC addresses, IPv4 ethertype.
    • IP_HEADER_1

      private static final byte[] IP_HEADER_1
      First half of the fake IP header.
    • IP_HEADER_2

      private static final byte[] IP_HEADER_2
      Second half of the fake IP header.
    • UNK_IP

      private static final byte[] UNK_IP
      Placeholder address of an unknown peer.
    • MY_UNK_IP

      private static final byte[] MY_UNK_IP
      Placeholder address of our side.
    • MAX_PAYLOAD_BYTES

      private static final int MAX_PAYLOAD_BYTES
      Max # of streaming lib payload bytes to dump.
      See Also:
    • MAX_OPTION_LEN

      private static final int MAX_OPTION_LEN
      Options - give our custom ones some mnemonics.
      See Also:
    • OPTION_END

      private static final byte OPTION_END
      Option marking the end of the options.
      See Also:
    • OPTION_MSS

      private static final byte OPTION_MSS
      Option carrying the maximum segment size.
      See Also:
    • OPTION_PING

      private static final byte OPTION_PING
      Option of the ping request.
      See Also:
    • OPTION_PONG

      private static final byte OPTION_PONG
      Option of the ping reply.
      See Also:
    • OPTION_SIGREQ

      private static final byte OPTION_SIGREQ
      Option requesting the signature.
      See Also:
    • OPTION_SIG

      private static final byte OPTION_SIG
      Option carrying the signature.
      See Also:
    • OPTION_RDELAY

      private static final byte OPTION_RDELAY
      Option carrying our receive delay.
      See Also:
    • OPTION_ODELAY

      private static final byte OPTION_ODELAY
      Option carrying our send delay.
      See Also:
    • OPTION_FROM

      private static final byte OPTION_FROM
      Option carrying the sender's port.
      See Also:
    • OPTION_NACK

      private static final byte OPTION_NACK
      Option of the negative ack.
      See Also:
    • _fos

      private final OutputStream _fos
      Stream the pcap records are written to.
    • _context

      private final I2PAppContext _context
      The app context.
    • _log

      private final Log _log
      Logger for the pcap writer.
  • Constructor Details

    • PcapWriter

      public PcapWriter(I2PAppContext ctx, String file) throws IOException
      Creates a new PcapWriter that writes to the specified file in the log directory.
      Parameters:
      ctx - the application context
      file - the filename to write (relative to the log directory)
      Throws:
      IOException - if the file cannot be opened or the header cannot be written
  • Method Details

    • close

      public void close()
      Closes the output stream, flushing any buffered data. Errors during close are silently ignored.
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
    • flush

      public void flush()
      Flushes any buffered data to the underlying output stream. Errors during flush are logged but do not interrupt operation.
      Specified by:
      flush in interface Flushable
    • write

      public void write(PacketLocal pkt) throws IOException
      Write an outbound packet to the pcap file.
      Parameters:
      pkt - the outbound packet to write
      Throws:
      IOException - if the packet cannot be written
    • write

      public void write(Packet pkt, Connection con) throws IOException
      Write an inbound packet to the pcap file.
      Parameters:
      pkt - the inbound packet to write
      con - the connection, may be null
      Throws:
      IOException - if the packet cannot be written
    • wrt

      private void wrt(Packet pkt, Connection con, boolean isInbound) throws IOException, DataFormatException
      Write a packet to the pcap file in the proper format.
      Parameters:
      pkt - the packet to write
      con - the connection, may be null
      isInbound - true if the packet is inbound
      Throws:
      IOException - if the packet cannot be written
      DataFormatException - if the packet data is malformed
    • getLowestAckedThrough

      private static long getLowestAckedThrough(Packet pkt)
      Calculate the lowest sequence number that has been acked through.
      Parameters:
      pkt - the packet containing ack information
      Returns:
      the lowest acked-through sequence number (at least 0)
    • update

      private static int update(int checksum, byte[] b)
      One's complement 2-byte checksum update.
      Parameters:
      checksum - the running checksum
      b - the data to incorporate
      Returns:
      the updated checksum
    • update

      private static int update(int checksum, byte[] b, int len)
      One's complement 2-byte checksum update.
      Parameters:
      checksum - the running checksum
      b - the data to incorporate
      len - the number of bytes to use from b
      Returns:
      the updated checksum