Transport Class
(CDP::IO::Transport)The Transport is a class used to simplify the handling of configurable communication in an IOServer. It provides methods to configure itself from XML, and it has functions to Read() and Write() data. More...
Header: | #include <IO/Transport.h> |
Inherits: | CDP::StudioAPI::CDPNode |
Inherited By: |
Public Types
enum | OpenMode { OpenMode_Send, OpenMode_Listen } |
Public Functions
Transport(const std::function<unsigned int( Transport *, char *, unsigned int ) > readCallbackHandler) | |
virtual void | Close() = 0 |
virtual void | Configure(XMLElementEx *transportElement, CDPComponent *owner) |
virtual double | GetTimeout() const = 0 |
virtual bool | IsError() = 0 |
virtual bool | IsOpen() const = 0 |
virtual bool | Open(OpenMode mode) = 0 |
virtual unsigned int | Read(char *data, unsigned int length, double timeout = 0.0) = 0 |
virtual unsigned int | ReadWithCallback(char *buffer, unsigned int length) |
virtual unsigned int | Write(const char *data, unsigned int length, double timeout = 0.0) = 0 |
Reimplemented Public Functions
virtual void | FillNodeChildren(CDP::StudioAPI::NodeStream &serializer) const override |
virtual const std::string | GetNodeName() const override |
virtual std::string | GetNodeTypeName() const override |
- 26 public functions inherited from CDP::StudioAPI::CDPNode
- 22 public functions inherited from CDP::StudioAPI::ICDPNode
Static Public Members
Transport * | Create(XMLElementEx *transportElement, CDPComponent *owner, const std::function<unsigned int( Transport *, char *, unsigned int ) > readCallbackHandler = {}) |
Additional Inherited Members
- 1 protected function inherited from CDP::StudioAPI::CDPNode
Detailed Description
The Transport is a class used to simplify the handling of configurable communication in an IOServer. It provides methods to configure itself from XML, and it has functions to Read() and Write() data.
Usage
The Transport is typically created from the Component HandleXMLElement function:
#include <IO/Transport.h> ... bool CustomIO::HandleXMLElement(XMLElementEx* pEx) { if (pEx->GetName()=="Transport") { m_transport = CDP::IO::Transport::Create(pEx,m_parent); if (m_transport==nullptr) Suspend(); else m_transport->Configure(pEx,this); return true; } return IOServer::HandleXMLElement(pEx); // call base }
The above code will cause the component to make one of the supported transport layers when they are encountered in the configuration.
To add a Transport table to a model, in Configure mode:
- Add a CDPModel -> AggregateBaseModel
- In the Elements table, rename AggregateBaseModel to Transport
- Set the Transport AcceptsBase column value to Transport to accept Transport models.
- Build the library to apply the changes; a table named Transport should now appear in your model.
To add a preconfigured UDP tranport to your model, in Configure mode, add a CDPCore -> UDPTransport. You can then pre-configure the transport by going into the UDPTransport in the Transport table.
In Code mode, the transport is initialized like this to open the transport in a master role
bool success = m_transport->Open(CDP::IO::Transport::OpenMode_Send);
... and it is closed like this:
try { m_transport->Close(); } catch (std::exception const& e) { CDPMessage("%s::Close() : %s\n",e.what()); } catch(...){ }
To write data to be sent on the transport:
unsigned int bytesSent = m_transport->Write(data,length);
To receive data from the transport:
double optionalTimeoutThatOverridesTransportConfiguration = 0.3; // seconds unsigned int dataRead = m_transport->Read(receiveBuffer,maxSize,optionalTimeoutThatOverridesTransportConfiguration);
Note: Make sure that blocking operations are done in separate thread(s) and not from Process()-functions or Message-handlers. This can easily be accomplished by inheriting the component from an IOServer.
Overriding the Transport
In some cases it might be neccessary to add information to a Transport configuration that is used f.i. in a user-made IOServer. One way to do this is to make a new model xml file which has <BaseModel>Transport</BaseModel> and copy all the Attribute descriptions from the required model (TCPTransport or UDPTransport). In the IOServer library code, derive from the most related Transport class (TCP or UDP) and add code to expose the attribute(s). The IOServer itself must then make a new instance of this new transport instead of calling CDP::IO::Transport::Create(...).
Example ExtendedTCPTransport:
#include <IO/TCPTransport.h> class ExtendedTCPTransport: public CDP::IO::TCPTransport { public: virtual void Configure(XMLElementEx* transportElement,CDPComponent* owner); virtual void FillNodeChildren(CDP::StudioAPI::NodeStream &serializer) const override; };
void ExtendedTCPTransport::Configure(XMLElementEx *transportElement, CDPComponent *owner) { TCPTransport::Configure(transportElement,owner); auto flags = System::Base::PropertyCreateFlags()|System::Base::e_PropertyReadOnly | System::Base::e_PropertyReparent; System::Base::PropertyCreate(m_extraAttribute,owner,"ExtraAttribute",flags,transportElement); }
void ExtendedTCPTransport::FillNodeChildren(CDP::StudioAPI::NodeStream &serializer) const { TCPTransport::FillNodeChildren(serializer); serializer << CDP::StudioAPI::AbsorbedChild(m_extraAttribute); }
See also NetworkTransport, TCPTransport, UDPTransport, and SerialTransport.
Member Type Documentation
enum Transport::OpenMode
This enum type specifies how the transport will be used:
Constant | Value | Description |
---|---|---|
CDP::IO::Transport::OpenMode_Send | 0 | The Transport will be used as a master, i.e. send, then receive. |
CDP::IO::Transport::OpenMode_Listen | 1 | The Transport will be used as a slave, i.e. listen / receive, then respond. |
Member Function Documentation
Transport::Transport(const std::function<unsigned int( Transport *, char *, unsigned int ) > readCallbackHandler)
Constructs the Transport, setting up the optional readCallbackHandler.
[pure virtual]
void Transport::Close()
Disconnects from the remote and Closes the transport.
[virtual]
void Transport::Configure(XMLElementEx *transportElement, CDPComponent *owner)
Maps the Name property to its configuration and stores the owner component
[static]
Transport *Transport::Create(XMLElementEx *transportElement, CDPComponent *owner, const std::function<unsigned int( Transport *, char *, unsigned int ) > readCallbackHandler = {})
Creates and returns UDP,TCP or Serial transports if possible, or nullptr if not.
[override virtual]
void Transport::FillNodeChildren(CDP::StudioAPI::NodeStream &serializer) const
Reimplemented from CDPNode::FillNodeChildren().
Serializes name
[override virtual]
const std::string Transport::GetNodeName() const
Reimplemented from ICDPNode::GetNodeName().
Returns the configured name
[override virtual]
std::string Transport::GetNodeTypeName() const
[pure virtual]
double Transport::GetTimeout() const
Returns the configured Timeout
[pure virtual]
bool Transport::IsError()
Returns true if there is an error present.
[pure virtual]
bool Transport::IsOpen() const
Returns true if the Transport is currently successfully open, false if not.
[pure virtual]
bool Transport::Open(OpenMode mode)
Opens the transport and connects to remote if the transport supports it.
The implementation of this function should be such that after returning true, the Transport should be ready for the Read() and/or Write() calls.
[pure virtual]
unsigned int Transport::Read(char *data, unsigned int length, double timeout = 0.0)
Reads length number of data from transport into data, within timeout.
[virtual]
unsigned int Transport::ReadWithCallback(char *buffer, unsigned int length)
Reads data from the transport and then calls the Read callback with Transport pointer, buffer and length for additional processing.
[pure virtual]
unsigned int Transport::Write(const char *data, unsigned int length, double timeout = 0.0)
Writes length bytes of data to the transport within timeout.
Get started with CDP Studio today
Let us help you take your great ideas and turn them into the products your customer will love.