/*! \file piconnection.h * \brief Complex I/O point */ /* PIP - Platform Independent Primitives Complex I/O point Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef PICONNECTION_H #define PICONNECTION_H #include "pipacketextractor.h" class PIP_EXPORT PIConnection: public PIObject { PIOBJECT(PIConnection) public: //! Constructs an empty connection PIConnection(); //! Constructs connection and configure it from config file "config" from section "name" PIConnection(const PIString & config, const PIString & name); ~PIConnection(); /*! \brief Configure connection from config file "config" from section "name". Returns if configuration was successful * \details \b Warning: all devices, filters and channels removed before configure! */ bool configureFromConfig(const PIString & config, const PIString & name); //! Returns config file section of current connection configuration PIString makeConfig() const; /*! \brief Add device with full path "full_path", open mode "mode" to Device pool and connection * \details Returns pointer to device or null if device can not be created. If "start" is true, * read thread is started immediately. Else, you can start read thread with functions \a startThreadedRead() * or \a startAllThreadedReads(). By default, read thread doesn`t start */ PIIODevice * addDevice(const PIString & full_path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = false); /*! \brief Remove device with full path "full_path" from connection * \details Returns if device was removed. If there is no connection bounded to this device, * it will be removed from Device pool */ bool removeDevice(const PIString & full_path); /*! \brief Remove all device from connection * \details If there is no connection bounded to there devices, they removed from Device pool */ void removeAllDevices(); //! Returns device with full path "full_path" or null if there is no such device PIIODevice * device(const PIString & full_path) const; //! Returns all devices bounded to this connection PIVector boundedDevices() const; /*! \brief Add filter with name "name" to device with full path "full_path" * \details If there is no filter with name "name", connection create new with split mode "mode" and bound * to it device "full_path". If filter with name "name" already exists, device "full_path" add to this filter. * \b Attention! "mode" is altual olny if new filter was created! * This function returns PIPacketExtractor * assosiated with this filter */ PIPacketExtractor * addFilter(const PIString & name, const PIString & full_path, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None); //! Add filter with name "name" to device "dev" PIPacketExtractor * addFilter(const PIString & name, const PIIODevice * dev, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None); /*! \brief Remove from filter with name "name" device with full path "full_path" * \details If there is no devices bounded to this filter, it will be removed. Returns * if device was removed */ bool removeFilter(const PIString & name, const PIString & full_path); //! Remove from filter with name "name" device "dev" bool removeFilter(const PIString & name, const PIIODevice * dev); //! Remove filter with name "name". Returns if filter was removed bool removeFilter(const PIString & name); //! Remove all filters from connection void removeAllFilters(); //! Returns all filters of connection PIVector filters() const; //! Returns all filter names of connection PIStringList filterNames() const; //! Returns PIPacketExtractor * assosiated with filter "name" or null if there is no such filter PIPacketExtractor * filter(const PIString & name) const; //! Returns all devices bounded to filter "name" PIVector filterBoundedDevices(const PIString & name) const; /*! \brief Add to connection channel from "name_from" to "name_to" * \details "name_from" and "name_to" can be full pathes of devices or filter names. * Returns \b false if there if no such device or filter, else create channel and returns \b true */ bool addChannel(const PIString & name_from, const PIString & name_to); //! Add to connection channel from "name_from" to "dev_to" bool addChannel(const PIString & name_from, const PIIODevice * dev_to) {return addChannel(name_from, devFPath(dev_to));} //! Add to connection channel from "dev_from" to "name_to" bool addChannel(const PIIODevice * dev_from, const PIString & name_to) {return addChannel(devFPath(dev_from), name_to);} //! Add to connection channel from "dev_from" to "dev_to" bool addChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {return addChannel(devFPath(dev_from), devFPath(dev_to));} /*! \brief Remove from connection channel from "name_from" to "name_to" * \details "name_from" and "name_to" can be full pathes of devices or filter names. * Returns \b false if there if no such device or filter, else remove channel and returns \b true */ bool removeChannel(const PIString & name_from, const PIString & name_to); //! Remove from connection channel from "name_from" to "dev_to" bool removeChannel(const PIString & name_from, const PIIODevice * dev_to) {return removeChannel(name_from, devFPath(dev_to));} //! Remove from connection channel from "dev_from" to "name_to" bool removeChannel(const PIIODevice * dev_from, const PIString & name_to) {return removeChannel(devFPath(dev_from), name_to);} //! Remove from connection channel from "dev_from" to "dev_to" bool removeChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {return removeChannel(devFPath(dev_from), devFPath(dev_to));} /*! \brief Remove from connection all channels from "name_from" * \details "name_from" can be full path of device or filter name. * Returns \b false if there if no such device or filter, else remove channels and returns \b true */ bool removeChannel(const PIString & name_from); //! Remove from connection all channels from "dev_from" bool removeChannel(const PIIODevice * dev_from) {return removeChannel(devFPath(dev_from));} //! Remove from connection all channels void removeAllChannels(); //! Returns all channels of this connection as full pathes or filter names pair array (from, to) PIVector > channels() const; //! Start read thread of device with full path "full_path" void startThreadedRead(const PIString & full_path); //! Start read thread of device "dev" void startThreadedRead(const PIIODevice * dev) {startThreadedRead(devFPath(dev));} //! Start read threads of all Device pool device void startAllThreadedReads(); //! Stop read thread of device with full path "full_path" void stopThreadedRead(const PIString & full_path); //! Stop read thread of device "dev" void stopThreadedRead(const PIIODevice * dev) {stopThreadedRead(devFPath(dev));} //! Stop read threads of all Device pool device void stopAllThreadedReads(); //! Returns if there is no devices in this connection bool isEmpty() const {return device_modes.isEmpty();} //! Write data "data" to device with full path "full_path" and returns result of \a write() function of device int write(const PIString & full_path, const PIByteArray & data); //! Returns all connections in application static PIVector allConnections(); //! Returns all devices in Device pool static PIVector allDevices(); class DevicePool: public PIObject { PIOBJECT(DevicePool) friend class PIConnection; public: DevicePool(): PIObject("PIConnection::DevicePool") {} PIIODevice * addDevice(PIConnection * parent, const PIString & fp, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = true); bool removeDevice(PIConnection * parent, const PIString & fp); void unboundConnection(PIConnection * parent); PIIODevice * device(const PIString & fp) const; PIVector boundedConnections() const; PIVector boundedDevices() const; PIVector boundedDevices(const PIConnection * parent) const; protected: struct DeviceData { DeviceData(): dev(0), rthread(0), started(false) {} ~DeviceData(); PIIODevice * dev; PIThread * rthread; bool started; PIVector listeners; }; static void threadReadDP(void * ddp); void deviceReaded(DeviceData * dd, const PIByteArray & data); typedef PIMap::value_type DDPair; PIMap devices; }; EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data) EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data) //! \events //! \{ //! \fn void dataReceivedEvent(const PIString & from, const PIByteArray & data) //! \brief Raise on data received from device with full path "from" //! \fn void packetReceivedEvent(const PIString & from, const PIByteArray & data) //! \brief Raise on packet received from filter with name "from" //! \} protected: //! Executes on data received from device with full path "from" virtual void dataReceived(const PIString & from, const PIByteArray & data) {} //! Executes on packet received from filter with name "from" virtual void packetReceived(const PIString & from, const PIByteArray & data) {} //! Validate header "rec" with source header "src" and size "size", executes from filter "filter_name" virtual bool filterValidateHeader(const PIString & filter_name, uchar * src, uchar * rec, int size); //! Validate footer "rec" with source footer "src" and size "size", executes from filter "filter_name" virtual bool filterValidateFooter(const PIString & filter_name, uchar * src, uchar * rec, int size); //! Validate payload "rec" with size "size", executes from filter "filter_name" virtual bool filterValidatePayload(const PIString & filter_name, uchar * rec, int size); private: static bool filterValidateHeaderS(void * c, uchar * src, uchar * rec, int size); static bool filterValidateFooterS(void * c, uchar * src, uchar * rec, int size); static bool filterValidatePayloadS(void * c, uchar * rec, int size); void rawReceived(PIIODevice * dev, const PIString & from, const PIByteArray & data); void unboundExtractor(PIPacketExtractor * pe); EVENT_HANDLER2(void, packetExtractorReceived, uchar * , data, int, size); PIString devPath(const PIIODevice * d) const; PIString devFPath(const PIIODevice * d) const; struct Extractor { Extractor(): extractor(0) {} ~Extractor(); PIPacketExtractor * extractor; PIVector devices; }; typedef PIMap::value_type PEPair; typedef PIMap >::value_type BEPair; typedef PIMap >::value_type CPair; PIMap extractors; PIMap device_modes; PIMap > bounded_extractors; PIMap > channels_; static PIVector _connections; }; extern PIConnection::DevicePool * __device_pool__; class __DevicePoolContainer__ { public: __DevicePoolContainer__(); static bool inited_; }; static __DevicePoolContainer__ __device_pool_container__; #endif // PICONNECTION_H