Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / C++

RCF - Interprocess Communication for C++

Rate me:
Please Sign up or sign in to vote.
4.94/5 (147 votes)
25 Oct 2011CPOL20 min read 4.6M   8.4K   331  
A server/client IPC framework, using the C++ preprocessor as an IDL compiler.
//*****************************************************************************
// RCF - Remote Call Framework
// Copyright (c) 2005. All rights reserved.
// Developed by Jarl Lindrud.
// Contact: jlindrud@hotmail.com .
//*****************************************************************************

#ifndef INCLUDE_RCF_ASYNCFILTER_HPP
#define INCLUDE_RCF_ASYNCFILTER_HPP

#include <string>
#include <vector>

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>

namespace RCF {

    /// Runtime description of a filter.
    class FilterDescription
    {
    public:
        FilterDescription(const std::string &filterName, int filterId) : mFilterName(filterName), mFilterId(filterId)
        {}

        std::string getName() const
        {
            return mFilterName;
        }

        int getId() const
        {
            return mFilterId;
        }

    private:
        std::string mFilterName;
        int mFilterId;
    };

    /// Interface for synchronous/asynchronous communications filters.
    class Filter
    {
    public:
        typedef boost::function2<void, char *, std::size_t>          ReadFunction;
        typedef boost::function2<void, const char *, std::size_t>    WriteFunction;
        typedef boost::function2<void, std::size_t, int>             ReadWriteCompletionCallback;

        /// Virtual destructor.
        virtual ~Filter()
        {}

        /// Reads data from the filter.
        /// \param buffer Buffer to transfer data to.
        /// \param bufferLen Maximum count of bytes to transfer.
        virtual void read(char *buffer, std::size_t bufferLen) = 0;

        /// Writes data to the filter.
        /// \param buffer Buffer from which to transfer data.
        /// \param bufferLen Maximum count of bytes to transfer.
        virtual void write(const char *buffer, std::size_t bufferLen) = 0;

        /// Callback, generally invoked by the next filter downstream in a filter chain, upon completion of a read or write request.
        /// \param bytesTransferred Count of bytes transferred.
        /// \param error -1 for error, otherwise 0.
        virtual void onReadWriteCompleted(std::size_t bytesTransferred, int error) = 0;

        /// Provides a runtime description of the filter.
        /// \return FilterDescription structure.
        virtual FilterDescription getFilterDescription() const = 0;

        // TODO: name these functions better (too ambiguous)

        /// Sets the downstream read function.
        virtual void setReadFunction( ReadFunction readFunction ) = 0;

        /// Sets the downstream write function.
        virtual void setWriteFunction( WriteFunction writeFunction ) = 0;

        /// Sets the upstream read/write completion callback.
        virtual void setReadWriteCompletionCallback( ReadWriteCompletionCallback readWriteCompletionCallback ) = 0;

        /// Gets a functor wrapping the filters read() function.
        virtual ReadFunction getReadFunction() = 0;

        /// Gets a functor wrapping the filters write() function.
        virtual WriteFunction getWriteFunction() = 0;

        /// Gets a functor wrapping the filters read/write completion callback.
        virtual ReadWriteCompletionCallback getReadWriteCompletionCallback() = 0;
    };

    static const int RCF_FILTER_IDENTITY = 1;
    static const int RCF_FILTER_XOR = 101;

    /// Trivial identity filter, applies no transformations at all. Also serves as a convenience base class for other filters.
    class IdentityFilter : public Filter
    {
    public:
        IdentityFilter();
        void read(char *buffer, std::size_t bufferLen);
        void write(const char *buffer, std::size_t bufferLen);
        void onReadWriteCompleted(std::size_t bytesTransferred, int error);
        void setReadFunction( ReadFunction readFunction );
        void setWriteFunction( WriteFunction writeFunction );
        void setReadWriteCompletionCallback( ReadWriteCompletionCallback readWriteCompletionCallback );
        ReadFunction getReadFunction();
        WriteFunction getWriteFunction();
        ReadWriteCompletionCallback getReadWriteCompletionCallback();
        FilterDescription getFilterDescription() const;
        static FilterDescription sGetFilterDescription();

    protected:
        ReadFunction mReadFunction;
        WriteFunction mWriteFunction;
        ReadWriteCompletionCallback mReadWriteCompletionCallback;
    };

    class XorFilter : public IdentityFilter
    {
    public:
        static FilterDescription sGetFilterDescription();
        FilterDescription getFilterDescription() const;
        XorFilter();
        void read(char *buffer, std::size_t bufferLen);
        void write(const char *buffer, std::size_t bufferLen);
        void onReadWriteCompleted(std::size_t bytesTransferred, int error);
    private:
        char mMask;
        char *mBuffer;
        std::size_t mBufferLen;
        std::vector<char> mPostBuffer;
        bool mReading;
    };
    
    typedef boost::shared_ptr<Filter> FilterPtr;

    /// Interface for filter factories.
    class FilterFactory
    {
    public:

        /// Virtual destructor.
        virtual ~FilterFactory()
        {}

        /// Creates a filter.
        /// \return Pointer to newly created filter.
        virtual FilterPtr createFilter() = 0;

        /// Returns a runtime description of the filters that this factory produces.
        /// \return FilterDescription structure.
        virtual FilterDescription getFilterDescription() = 0;
    };

    typedef boost::shared_ptr<FilterFactory> FilterFactoryPtr;

    /// Factory for IdentityFilter.
    class IdentityFilterFactory : public FilterFactory
    {
    public:
        FilterPtr createFilter();
        FilterDescription getFilterDescription();
    };

    class XorFilterFactory : public FilterFactory
    {
    public:
        FilterPtr createFilter();
        FilterDescription getFilterDescription();
    };

    /// Utility for comparing filters and filter id's.
    struct FilterIdComparison
    { 
        bool operator()(FilterPtr filterPtr, int filterId) 
        { 
            return filterPtr->getFilterDescription().getId() == filterId;
        } 
    };

    /// Connects a chain of filters (hooks up read and write functions of adjacent filters).
    /// \param filters A vector of filters to connect.
    void connectFilters(const std::vector<FilterPtr> &filters);
    
    /// Connects a chain of filters (hooks up read and write functions of adjacent filters).
    /// \param filters A vector of filters to connect.
    /// \param readFunction Read function to apply to the final filter.
    /// \param writeFunction Write function to apply to the final filter.
    /// \param readWriteCompletionCallback Callback to apply to the initial filter.
    void connectFilters(
        const std::vector<FilterPtr> &filters, 
        Filter::ReadFunction readFunction, 
        Filter::WriteFunction writeFunction, 
        Filter::ReadWriteCompletionCallback readWriteCompletionCallback);

    /// Filters data through the given filters.
    /// \param unfilteredData Unfiltered data.
    /// \param filteredData Filtered data.
    /// \param filters Filter chain to filter data through.
    bool filterData(
        const std::string &unfilteredData, 
        std::string &filteredData, 
        const std::vector<FilterPtr> &filters);

    /// Unfilters data through the given filters.
    /// \param filteredData Filtered data.
    /// \param unfilteredData Unfiltered data.
    /// \param unfilteredDataLen Length of unfiltered data.
    /// \param filters Filter chain to unfilter data through.
    bool unfilterData(
        const std::string &filteredData, 
        std::string &unfilteredData, 
        std::size_t unfilteredDataLen, 
        const std::vector<FilterPtr> &filters);

} // namespace RCF

#endif // ! INCLUDE_RCF_ASYNCFILTER_HPP

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
Software developer, from Sweden and now living in Canberra, Australia, working on distributed C++ applications. When he is not programming, Jarl enjoys skiing and playing table tennis. He derives immense satisfaction from referring to himself in third person.

Comments and Discussions