class io.Pcap

Overview

This class provides high-level asynchronous interface for the Pcap (Packet Capture) library. More…

import "io_pcap.jncx"

class Pcap {
    // enums

    enum Defaults;

    // fields

    string_t readonly m_filter;
    io.PcapEvents readonly volatile m_activeEvents;
    std.Error const* readonly volatile m_ioError;
    bool readonly m_isOpen;

    // properties

    io.PcapLinkType const property m_linkType;
    bool autoget property m_isPromiscious;
    uint_t autoget property m_readTimeout;
    size_t property m_snapshotSize;
    size_t autoget property m_kernelBufferSize;
    size_t autoget property m_readBufferSize;

    // construction

    construct();
    destruct();

    // methods

    bool errorcode openDevice(string_t deviceName);

    bool errorcode openLive(
        string_t deviceName,
        string_t filter = null,
        uint_t snapshotSize = Defaults.SnapshotSize,
        bool isPromiscious = Defaults.IsPromiscious,
        uint_t readTimeout = Defaults.ReadTimeout
    );

    bool errorcode openFile(
        string_t fileName,
        string_t filter = null
    );

    void close();
    bool errorcode activate(string_t filter = null);

    bool errorcode setFilter(
        string_t filter,
        bool isOptimized = true,
        uint32_t netMask = -1
    );

    size_t errorcode read(
        void* p,
        size_t size,
        uint64_t* timestamp = null
    );

    size_t errorcode write(
        void const* p,
        size_t size
    );

    long errorcode wait(
        io.PcapEvents eventMask,
        void function* handler(io.PcapEvents triggeredEvents)
    );

    bool errorcode cancelWait(long handle);

    io.PcapEvents blockingWait(
        io.PcapEvents eventMask,
        uint_t timeout = -1
    );

    import io.Pcap.PcapEvents async asyncWait(io.PcapEvents eventMask);

    // aliases

    alias dispose = close;
};

Detailed Documentation

This class provides high-level asynchronous interface for the Pcap (Packet Capture) library.

Pcap library(called WinPcap on Windows) is de-facto the standard tool for capturing and injecting low-level network traffic.

A typical sequence of steps when working with io.Pcap looks something like this:

  • Open a live capture using openDevice or a capture file(*.pcap) using openFile method;

  • Assign IO event handler with wait method. You would probably also want to schedule your event handler to be run in particular environment(e.g., in a specific thread) and partially apply some syncrhonization ID to discard late events;

  • When io.PcapEvents.IncomingData event is fired, read packet using read method;

  • If you opened a live capture, you can also inject packets with write method;

  • Close Pcap object when no longer needed with close method.

Code sample:

class MyDialog {
    // ...

    io.Pcap m_pcap;
    uint_t m_syncId;

    void startCapture(
        string_t device,
        string_t filter = null
    );

    void close();
    void waitPcapEvents();

    void onPcapEvent(
        uint_t syncId,
        io.PcapEvents triggeredEvents
    );
}

MyDialog.startCapture(
    string_t device,
    string_t filter = null
) {
    bool result = try m_pcap.openDevice(device, filter);
    if (!result) {
        // handle the error...
    }

    waitPcapEvents();
}

MyDialog.close() {
    m_serial.close();
    m_syncId++; // events past this point will be discarded as 'late'
}

MyDialog.waitPcapEvent() {
    io.PcapEvents eventMask =
        io.PcapEvents.IoError |
        io.PcapEvents.IncomingData;

    m_serial.wait(eventMask, onPcapEvent ~(++m_syncId) @
        g_mainThreadScheduler);
}

MyDialog.onPcapEvent(
    uint_t syncId,
    io.PcapEvents triggeredEvents
) {
    if (syncId != m_syncId) // late event
        return;

    if (triggeredEvents & io.PcapEvents.IoError) {
        string_t errorString = m_pcap.m_ioError.m_description;
        // ...
    }

    if (triggeredEvents & io.PcapEvents.IncomingData) {
        char buffer[256];
        size_t size = m_pcap.read(buffer, sizeof(buffer));
        // ...
    }

    waitPcapEvents(); // restart wait
}

See also:

io.PcapEvents

Fields

string_t readonly m_filter

Holds currently specified capture filter [3].

bool readonly m_isOpen

Holds the open status for the Pcap object, i.e. true if opened; false otherwise.

Methods

bool errorcode openDevice(string_t deviceName)

Opens a network interface for Pcap capture.

Returns true on success. If live capture on specified device could not be opened, function sets the error reported by Pcap and returns false [1].

bool errorcode openLive(
    string_t deviceName,
    string_t filter = null,
    uint_t snapshotSize = Defaults.SnapshotSize,
    bool isPromiscious = Defaults.IsPromiscious,
    uint_t readTimeout = Defaults.ReadTimeout
)

Opens a network interface for Pcap capture.

The function accepts 3 arguments. The first one, deviceName, is used to specify the device to start capture on. To obtain a list of available devices, use io.createPcapDeviceDescList function.

The second one, filter, allows you to specify a capture filter [3] which will be applied to incoming packets – packets which do not pass the filter, will never be signalled via io.PcapEvents.IncomingData event and could not be read by read method.

The third parameter specifies whether to put interface in promiscuous mode.

Returns true on success. If live capture on specified device could not be opened, function sets the error reported by Pcap and returns false [1].

bool errorcode openFile(
    string_t fileName,
    string_t filter = null
)

Opens a previously captured *.pcap file specified by fileName argument.

The second argument, filter, has the same meaning as in openDevice method [3].

Returns true on success. If capture file could not be opened, function sets the error reported by Pcap and returns false [1].

void close()

Closes a previously opened live capture or a capture file, does nothing if Pcap is not opened. This function always succeeds.

Sometimes it may be convenient to use disposable pattern to ensure timely invokation of close [2].

bool errorcode setFilter(
    string_t filter,
    bool isOptimized = true,
    uint32_t netMask = -1
)

Allows you to change current capture filter without restarting the capture.

Returns true on success. If capture filter could not be changed, function sets the error reported by Pcap and returns false [1].

size_t errorcode read(
    void* p,
    size_t size,
    uint64_t* timestamp = null
)

Reads the next packet into the buffer pointed to by p and size bytes long.

Returns the actual amount of bytes read or -1 if error occurs.

If read operation is unsuccessful, function sets the error reported by Pcap and returns -1 [1].

Normally you would call this function from within your event handler for ReadyRead event. If this function is called when there are no incoming pacets, it blocks until either a packet arrives, or Pcap is closed.

size_t errorcode write(
    void const* p,
    size_t size
)

Attempts to inject size bytes from the buffer pointed to by p as a packet on a currently opened device.

Returns the actual amount of bytes written on success. If write operation is unsuccessful, function sets the error reported by Pcap and returns -1 [1].

Aliases

alias dispose = close

Effectively makes io.Pcap a disposable class [2].


Footnotes