cc_tools_qt
Common Environment for Protocol Analysis.
Developing Custom Socket Plugin

The socket plugin is responsible to send the data over I/O link when requested as well as report any incoming data via callback. The CommsChampion Tools Project contains implementation of multiple available plugins It is recommended to follow this tutorial while looking at available examples. The easy ones are null_socket and echo_socket

Socket Class

To implement the required functionality the plugin's code must define its socket class inheriting from cc_tools_qt::Socket.

class MySocket : public cc_tools_qt::Socket
{
...
};
Main polymorphic interface class for sockets.
Definition: Socket.h:39

If socket implementation uses Qt signals/slots infrastructure, it can use multiple inheritance and extend QObject as well.

class MySocket : public QObject, public cc_tools_qt::Socket
{
Q_OBJECT
...
private slots:
...
};

The cc_tools_qt::Socket class is implemented using
Non-Virtual Interface Idiom It's non-virtual public interface is used by the driving application. The inheriting class needs to implement virtual *Impl() functions to override the default behaviour.

Connection / Disconnection

The actual socket class is expected to override virtual cc_tools_qt::Socket::socketConnectImpl() and cc_tools_qt::Socket::socketDisconnectImpl() functions.

class MySocket : public cc_tools_qt::Socket
{
public:
MySocket();
protected:
virtual bool socketConnectImpl() override;
virtual void socketDisconnectImpl() override;
};
virtual bool socketConnectImpl()
Polymorphic socket connection functionality implementation.
virtual void socketDisconnectImpl()
Polymorphic socket disconnection functionality implementation.

The connection request is used to open the device file or low level I/O socket, as well as to connect to remote host in case of network socket, such as TCP/IP Client.

When disconnection request comes in, the socket object is expected to disconnect from remote host (if applicable), and close the low level I/O socket.

Sometimes the unsolicited low level I/O socket disconnection can be detected. In this case, the socket object must use inherited cc_tools_qt::Socket::reportDisconnected() member function to report it to the running application. The latter will report it to the user.

NOTE, that during requested disconnection (inside overriden socketDisconnectImpl()) the socket class must NOT report the disconnection using the decribed above function. It should be used only to report unsolicited one.

Data Reception

The socket object is expected to detect and report incoming data. It must be done asynchronously, hence it is recommended to use available signal/slot mechanism provided by the Qt framework. However, if can also be done using other third party code. In this case it is recommended to do such thing in separate thread (especially if there are blocking calls involved) and communicate the updates to the main thread using the same signal/slot facility.

When new data arrival is detected, the socket object needs to report it using inherited cc_tools_qt::Socket::reportDataReceived() function. Note, that the latter receives single parameter of type cc_tools_qt::DataInfoPtr. It is std::shared_ptr to cc_tools_qt::DataInfo. Please use cc_tools_qt::makeDataInfo() function to allocate one. The cc_tools_qt::DataInfo contains three data members:

  • m_timestamp - timestamp when data is received
  • m_data - raw bytes data
  • m_extraProperties - optional extra information about the data.
class MySocket : public ...
{
private:
// internal member function to be called when new data arrives
void dataReceived(const std::uint8_t* buf, std::size_t len)
{
data->m_timestamp = cc_tools_qt::DataInfo::TimestampClock::now();
data->m_data.assign(buf, buf + len);
reportDataReceived(std::move(data));
}
};
void reportDataReceived(DataInfoPtr dataPtr)
Report new data has been received.
CC_API DataInfoPtr makeDataInfo()
Dynamically allocate DataInfo and return in in DataInfoPtr;.

NOTE, that the assignment of the m_timestamp value can be omitted. If no value has been set, the inherited reportDataReceived() function will assign the value returned by call to cc_tools_qt::DataInfo::TimestampClock::now() prior to invoking the callback to report the data to the application.

Also note, that there is m_extraProperties data member which can contain any extra information about the data. For example, the IP address and port the data has arrived from in case of network socket. Such extra information can be reported by the driving application when reporting received message details. For example, take a look at TCP/IP Server Socket implementation.

Sending Data

The socket object receives requests to send outgoing data using call to overridden virtual sendDataImpl() (see cc_tools_qt::Socket::sendDataImpl()).

class MySocket : public ...
{
protected:
virtual void sendDataImpl(cc_tools_qt::DataInfoPtr dataPtr) override
{
... // write contents of dataPtr->m_data to I/O socket.
}
};
virtual void sendDataImpl(DataInfoPtr dataPtr)=0
Polymorphic data send functionality implementation.
std::shared_ptr< DataInfo > DataInfoPtr
Pointer to DataInfo.
Definition: DataInfo.h:57

Note, that the parameter to the function is the same std::shared_ptr to cc_tools_qt::DataInfo. In addition to raw data bytes in may also contain extra properties. Depending on the socket, these properties can be used by the other plugins (filters and/or protocol) to provide extra information on how the data needs to be sent. For example, it can specify whether UDP/IP Socket needs to broadcast the provided data or send it directly to currently connected remote endpoint.

Reporting Errors

If there is any error discovered, the socket object is expected to report them using inherited cc_tools_qt::Socket::reportError() member function.

Plugin Class

Please read the Defining a Plugin page first to understand the way the plugins are defined.

The socket plugin must provide a callback to allocate the Socket object (the one that is derived from cc_tools_qt::Socket).

class EchoSocketPlugin : public cc_tools_qt::Plugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "cc.EchoSocketPlugin" FILE "echo_socket.json")
Q_INTERFACES(cc_tools_qt::Plugin)
public:
EchoSocketPlugin()
{
[this]()
{
return makeEchoSocket();
});
}
...
};
PluginProperties & setSocketCreateFunc(SocketCreateFunc &&func)
Assign callback for Socket allocation.
Interface class for plugin definition.
Definition: Plugin.h:39
PluginProperties & pluginProperties()
Get access to plugin properties.

If the socket requires configuration, please also provide a callback which creates the widget when invoked (see Configuration Widget).