adding filtering functionality on-the-fly in c++

103 views Asked by At

I have the following (simplified) architecture:

client(s) --> bouncer --> server

The clients send commands to the server. The 'bouncer' performs sanity and other checks on the commands issued by the client, and prevents faulty commands from reaching the server. For example, the bouncer may have the following code:

bool Bouncer::someCommand(const someCommandArg& arg) {
    if (arg.x < 100) {
        return false;                              
    }

    if (arg.y > 10) {
        return false;
    }
    // more checks ...

        return server->someCommand(arg);
}

The problem with this approach is that the bouncer conditions have to be hard-coded one by one, and is not flexible enough. I'm looking for a way to define these conditions in some configuration file, which the bouncer will load when created, and will loop through all the conditions when someCommand is called. Moreover, the test loop itself has to be fast.

Were it C#, I guess I would have used its compile-on-the-fly capabilities, and have my if clauses written in plain code in the configuration file. What do you suggest for C++?

2

There are 2 answers

0
Tony Delroy On BEST ANSWER

Choices include:

  • create an interpretive environment, communicate the testable aspects of the incoming message to it, and load some predicate expression/function from your config to be evaluated
    • embed a language (e.g. LUA, ruby)
    • download any of many simpler expression evaluation libraries
    • create your own (perhaps using boost Spirit)
  • have the bouncer load the predicates in the form of a shared object (.so, .dll - whatever your OS calls them) using dlopen/dlsym etc..
    • only the predicates/rules need be recompiled
    • don't need to distribute the entire app source to users wanting to specify predicates
    • pretty fast predicate execution

What's best depends a lot on the complexity of useful predicates, performance requirements, deployment practices etc..

0
Dirk On

You can use a plugin approach. Make the bouncer a plugin and then use a pipeline/chain-of-responsibility pattern to pass a command through multiple bouncers? Different bouncer plugins can check for different conditions and by chaining them, you define the final rule applied to the command. You can use a config file to specify what plugins should be loaded and how to setup the chain.

This still implies that the plugins have to be compiled before you can load them, but you can dynamically load them while your program is running if this is really a requirement. At least adding new plugins doesn't require your application to be recompiled.