telnetpp icon indicating copy to clipboard operation
telnetpp copied to clipboard

Sample of use Telnet++ with Qt5

Open kafeg opened this issue 1 year ago • 1 comments

Hello! First of all thanks much for this awesome library! This is not a bug report.

Just wanted to provide and keep a quick sample how to integrate Telnet++ to the Qt-based app to work together with QTcpSocket.

This is not fully working example, but just let developers know how to create channel, session and socket and how to link them to each other.


#include <telnetpp/session.hpp>

struct TelnetPPQtChannel
{
    // called internally from telnetpp::session::async_callback to forward result data from socket to app
    void async_read(std::function<void (telnetpp::bytes)> const &callback) {
        read_callback_ = callback;
    }
    
    // called internall from telnetpp::session::write to write data to socket
    void write(telnetpp::bytes data) {
        socket.write(QByteArray(reinterpret_cast<const char*>(data.data()), data.size()));
    }
    
    // called internall from telnetpp::session to check is socket still alive
    bool is_alive() const {
        return socket.state() == QAbstractSocket::ConnectedState;
    }
    
    // called internall from telnetpp::session, can force disconnect socket based on Telnet protocol
    void close() {
        socket.close();
    }
    
    // called from app code to forward raw socket data to Telnet++
    void receive(telnetpp::bytes data) {
        if (read_callback_)
            read_callback_(data);
    }

    QTcpSocket &socket;
    std::function<void (telnetpp::bytes)> read_callback_;
};

void TelnetPPQtSample()
{
    // create all classes and join them together
    QTcpSocket          socket;
    TelnetPPQtChannel   channel{socket};
    telnetpp::session   session{channel};
    
    // sample receive data from socket and write to Telnet++ session/channel
    QObject::connect(&socket, &QTcpSocket::readyRead, [&](){
        QByteArray  ba = socket.readAll();

        telnetpp::bytes content(reinterpret_cast<const telnetpp::byte*>(ba.constData()),
                                reinterpret_cast<const telnetpp::byte*>(ba.constData() + ba.size()));

        channel.receive(content); // forward all received from socket data to the session/channel
    });
    
    // sample read processed data from Telnet++ session/channel
    session.async_read([](telnetpp::bytes data) {
        QByteArray ba = QByteArray(reinterpret_cast<const char*>(data.data()), data.size());

        // ... do something with received and processed over Telnet++ data ...
    });
    
    // connect to host
    socket.connectToHost(127.0.0.1, 23); // just sample telnet host/port
    socket.waitForConnected();
    
    // sample send data to the socket over preprocess with Telnet++ session/channel
    QByteArray sampleData = "hello!";
    if(socket.state() == QAbstractSocket::ConnectedState)
    {
        telnetpp::bytes content(reinterpret_cast<const telnetpp::byte*>(sampleData.constData()),
                                reinterpret_cast<const telnetpp::byte*>(sampleData.constData() + sampleData.size()));
        session.write(content);
    }
    
    // ...
}

PS: Also updated vcpkg port to the newest version: https://github.com/microsoft/vcpkg/pull/36571

kafeg avatar Feb 04 '24 21:02 kafeg

Hi, @kafeg!

I really appreciate you letting me know that you found my library useful and awesome! Being able to knock together a bridge from QT to Telnet++ shows me that the type-erased Channel concept was definitely the right call.

Also, thanks for updating the version on vcpkg.

Although you said this isn't a bug report, I think it would be a good improvement to have an example that binds to QT using your code as a reference. I'll leave this issue here for that.

KazDragon avatar Feb 04 '24 22:02 KazDragon