Search code examples
c++c++11libtins

Libtins: cannot use class method as packet handler within the sniff_loop even with c++11


I'm working on an small UDP traffic sniffing example using libtins. Everything worked until I started encapsulating everythin into a class. Acording the tutorial (loop sniffing section), the snifer_loop takes a template functor as an argument, and:

The call to Sniffer::sniff_loop will make the sniffer start processing packets. The functor will be called using each processed packet as its argument. If at some point, you want to stop sniffing, then your functor should return false. Otherwise return true and the Sniffer object will keep looping.

The functor object will be copy constructed, so it must implement copy semantics. There is a helper template function which takes a pointer to an object of a template parameter type, and a member function, and returns a HandlerProxy. That object implements the required operator, in which it forwards the call to the member function pointer provided, using the object pointer given:

Everything works if I use PDU data type, or if I use Packet type with an external function, but once I use Packet type with a method, I get a compiler error:

c++ -Ihandler@sha -I. -I.. -I/usr/local/include/tins -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -std=c++11 -g -fPIC -MD -MQ 'handler@sh
a/handler.cpp.o' -MF 'handler@sha/handler.cpp.o.d' -o 'handler@sha/handler.cpp.o' -c ../handler.cpp
../handler.cpp: In constructor 'Reader::Reader()':
../handler.cpp:24:77: error: cannot convert 'bool (Reader::*)(Tins::Packet&)' to 'Tins::HandlerProxy<Reader>::fun_type {aka bool (Reader::*)(Tins::PDU&)}' for argument '2' to 'Tins::Handl
erProxy<T> Tins::make_sniffer_handler(T*, typename Tins::HandlerProxy<T>::fun_type) [with T = Reader; typename Tins::HandlerProxy<T>::fun_type = bool (Reader::*)(Tins::PDU&)]'
         sniffer.sniff_loop(make_sniffer_handler(this, &Reader::handlerPacket));

The tutorial specifies:

Packets can also be accepted on the functor object used on Sniffer::sniff_loop, but only when you are compiling in C++11 mode.

And I am using the c++11 switch.

#include <tins/tins.h>

using namespace Tins;

bool callbackPDU(PDU &pdu) {

    return true;
}

bool callbackPacket(Packet &packet) {

    return true;
}


class Reader
{
    Reader()
    {
        Sniffer sniffer("wlp3s0");
        // sniffer.sniff_loop(callbackPDU); // This works
        // sniffer.sniff_loop(callbackPacket); // This also works
        // sniffer.sniff_loop(make_sniffer_handler(this, &Reader::handlerPDU)); // This also works
        sniffer.sniff_loop(make_sniffer_handler(this, &Reader::handlerPacket)); // This doesn't work
    }

    bool handlerPDU(PDU &pdu)
    {
        return true;
    }

    bool handlerPacket(Packet &packet)
    {
        return true;
    }
};

int main()
{
    Reader reader();
}

class Functor
{
    Functor(){}

    bool operator()(Packet &packet)
    {
        return true;
    }
};

Solution

  • Ok, so according the library main developer, I should have used this:

    sniffer.sniff_loop(std::bind(&Reader::handlerPacket, this, std::placeholders::_1));
    

    And that worked like a charm.