I'm trying to write a server that handles protocol A over protocol B.
Protocol A is HTTP or RTSP, and protocol B is a simple sequence of binary packets:
[packet length][...encrypted packet data...]
So I want to use things like that:
boost::asio::async_read_until(socket, inputBuffer, "\r\n\r\n", read_handler);
However, instead of socket use some pseudo-socket connected to Protocol B handlers.
I have some ideas:
Forget about async_read, async_read_until, etc., and write two state machines for A and B.
Hybrid approach: async_read_* for protocol B, state machine for A.
Make internal proxy server.
I don't like (1) and (2) because
It's hard to decouple A from B (I want to be able to disable protocol B).
Ugly.
(3) just looks ugly :-)
So the question is: how do I implement this?
I have done something like your answer (2) in the past - using async_read calls to read the header first and then another async_read to read the length and forward the remaining things to a hand written state machine. But I wouldn't necessarily recommend that to you - You thereby might get zero-copy IO for protocol B but doing an IO call reading the 4-8 byte header is quite wasteful when you know there is always data coming behind it. And the problem is that your network abstraction for the 2 layers will be different - so the decoupling problem that you mention really exists.
Using a fixed length buffer, only calling async_read and then processing the data with 2 nested state machines (like you are basically proposing in answer (1)) works quite well. Your state machine for each would simple get pushed some new received data (from either directly the socket or from the lower state machine) and process that. This means A would not be coupled to B here, as you could directly push the data to the A state machine from asio, if the input/output data format matches.
Similar to this are the patterns that are used in the Netty and Facebook Wangle libraries, where you have handlers that get data pushed from a lower handler in the pipeline, perform their actions based on that input and output their decoded data to the next handler. These handlers can be state machines, but depending on the complexity of the protocol don't necessarily have to be. You can take some inspiration from that, e.g. look at some Wangle docs: https://github.com/facebook/wangle/blob/master/tutorial.md
If you don't want to push your data from one protocol handler to another but rather actively read it (most likely in an asynchronous fashion) you could also design yourself some interfaces (like ByteReader which implements an async_read(...) method or PacketReader which allows to read complete messages instead of bytes), implement them through your code (and ByteReader also through asio) and use them on the higher level. Thereby you are going from the push approach of data processing to a pull approach, which has some advantages and disadvantages.
I won't go over boost::asio, since this seems more a design pattern than a networking one.
I'd use the State Pattern. This way you could change protocol on the fly.
class net_protocol {
protected:
socket sock;
public:
net_protocol(socket _sock) : sock(_sock) {}
virtual net_protocol* read(Result& r) = 0;
};
class http_protocol : public net_protocol {
public:
http_protocol(socket _sock) : net_protocol(_sock) {}
net_protocol* read(Result& r) {
boost::asio::async_read_until(socket, inputBuffer, "\r\n\r\n", read_handler);
// set result, or have read_handler set it
return this;
}
};
class binary_protocol : public net_protocol {
public:
binary_protocol(socket _sock) : net_protocol(_sock) {}
net_protocol* read(Result& r) {
// read 4 bytes as int size and then size bytes in a buffer. using boost::asio::async_read
// set result, or have read_handler set it
// change strategy example
//if (change_strategy)
// return new http_strategy(sock);
return this;
}
};
You'd initialize the starting protocol with
std::unique_ptr<net_protocol> proto(new http_protocol(sock));
then you'd read with:
//Result result;
proto.reset(proto->read(result));
EDIT: the if() return new stragegy are, in fact, a state machine
if you are concerned about those async reads and thus can't decice which return policies, have the policy classes call a notify method in their read_handler
class caller {
std::unique_ptr<net_protocol> protocol;
boost::mutex io_mutex;
public:
void notify_new_strategy(const net_protocol* p) {
boost::unique_lock<boost::mutex> scoped_lock(mutex);
protocol.reset(p);
}
void notify_new_result(const Result r) { ... }
};
If you don't need to change used protocol on the fly you would have no need of State, thus read() would return Result (or, void and call caller::notify_new_result(const Result) if async). Still you could use the same approach (2 concrete classes and a virtual one) and it would probably be something very close to Strategy Pattern
Related
I am building a system where a top layer communicates with a driver layer, who in turn communicate with a I2C layer. I have put my I2C driver behind a message queue, in order to make it thread safe and serialize access to the I2C bus.
In order to return the reply to the driver, the I2C layer returns a std::future with a byte buffer inside that is filled out when the I2C bus read actually happens.
All this works and I like it.
My problem is that I also want the driver to return a future to the top layer, however this future will then depend on the previous future (when the I2C driver future-returns a byte buffer, the driver will have to interpret and condition those bytes to get the higher-level answer), and I am having problems making this dependency "nice".
For example, I have a driver for a PCT2075 temperature sensor chip, and I would like to have a:
future<double> getTemperature()
method in that driver, but so far I can't think of a better way than to make an intermediate "future-holder" class and then return that:
class PCT2075
{
public:
class TemperatureFuture
{
private:
std::future<std::pair<std::vector<uint8_t>, bool>> temperatureData;
public:
TemperatureFuture(std::future<std::pair<std::vector<uint8_t>, bool>> f);
template< class Clock, class Duration >
std::future_status wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time) const;
void wait() const; // wait and wait_until just waits on the internal future
double get();
};
TemperatureFuture getTemperature();
};
This structure works and I can go forward with it, but for some reason I am not super happy with it (though I can't quite explain why... :/ ).
So my questions are:
Is there some pattern that can make this better?
Would it make sense to let TemperatureFuture inherit directly from std::future (I have heard that "do not inherit from std classes" is a good rule)?
Or is this just how you do it, and I should stop worrying about nothing?
Ps. I also have another method whose answer relies on two I2C reads, and thus two different futures. It is possible to rework this to only have a one-on-one dependency, but the current way can handle the one-on-multiple variant so it would be nice if a potential new proposal also could.
You are looking for an operation called then, which as commenters note is sadly missing even in C++20.
However, it's not hard to write a then yourself.
template<typename Fun, typename... Ins>
std::invoke_result_t<Fun, Ins...> invoke_future(Fun fun, std::future<Ins>... futs) {
return fun(futs.get()...);
}
template<typename Fun, typename... Ins>
std::future<std::invoke_result_t<Fun, Ins...>> then(Fun&& fun, std::future<Ins>... futs) {
return std::async(std::launch::deferred, invoke_future<Fun, Ins...>, std::forward<Fun>(fun), std::move(futs)...);
}
I expect something like this wasn't standardised because it makes loads of assumptions about how the function should be run once the result is ready.
A future that just reinterprets the results of a previous future or gathers multiple futures is a good job for std::async(std::launch::deferred, ...). This doesn't launch any thread, it executes on request.
std::future<int> f1 = std::async([]() -> int { return 1; });
std::future<float> f2 = std::async(
std::launch::deferred,
[](std::future<int>&& f) -> float { return f.get(); },
std::move(f1));
std::printf("%f\n", f2.get());
The downside is that certain features will not work, e.g. wait_until.
If, instead, you need to launch a new asynchronous action once the first future is ready (e.g. send another I2C message, or compute the higher-level result in a thread pool), C++ does not offer any better solution than making this part of your original task. For example your I2C driver could accept a list of std::functions as callbacks.
I'am currently exploring the Asio library and have working code for regular TCP connections. I used asio::ip::tcp::iostream objects since stuff I want to transmit already can serialize to/deserialize from iostreams, so this was really handy and worked well for me.
I then tried to switch to SSL connections and that's when everything turned crazy. There is apparently no built-in support to get the same iostream interface that all other protocols support for a secured connection. From a design perspective this is really perplexing to me. Is there any reason why this is the case?
I am aware of the discussion in How to create a boost ssl iostream? which concludes with a wrapper class to provide iostream functionality using boost. Apart from that, according to a comment, the implementation is flawed, this also does not give the same interface as for the other protocols (a basic_socket_iostream) which also allows to e.g., set expiration times and close the connection. (I am also using asio in the non-boost version and want to avoid adding boost as an additional dependency if possible).
So, I guess my questions are:
What exactly would I need to implement to get a basic_socket_iostream for an SSL connection? I assume it would be a derivation of asio::basic_streambuf or asio::basic_socket_streambuf but I somehow can't figure out how they work and need to be tweaked.. there's just a bunch of weird pointer movement and buffer allocations and documentation to me is quite unclear on what happens when exactly to achieve what...
Why is this not already present in the first place? It seems very unreasonable to have this one protocol behave entirely different from any other and thus require major refactoring for changing a tcp::iostream based project to support secured connections
> Well, the problem I have is that the ssl::stream really does neither: I doesn't give a socket but it also doesn't give me a stream interface that would be compatible to those available from the other protocols and, yes, in that sense it behaves very differently from the others (for no apparent reason)
I don't think the stream behaves any differently from the other protocols (see
https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/overview/core/streams.html):
Streams, Short Reads and Short Writes
Many I/O objects in Boost.Asio are stream-oriented. This means that:
There are no message boundaries. The data being transferred is a continuous sequence of bytes.
Read or write operations may transfer fewer bytes than requested. This is referred to as a short read or short write.
Objects that provide stream-oriented I/O model one or more of the following type requirements:
SyncReadStream, where synchronous read operations are performed using a member function called read_some().
AsyncReadStream, where asynchronous read operations are performed using a member function called async_read_some().
SyncWriteStream, where synchronous write operations are performed using a member function called write_some().
AsyncWriteStream, where synchronous write operations are performed using a member function called async_write_some().
Examples of stream-oriented I/O objects include ip::tcp::socket, ssl::stream<>, posix::stream_descriptor, windows::stream_handle, etc.
Perhaps the confusion is that you're comparing to the iostream interface, which is simply not the same concept (it comes from the standard library).
To the question how you could make a iostream compatible stream wrapper for the ssl stream, I cannot devise an answer without consulting the documentations more and using a compiler, which I don't have on hand at the moment.
I think there is room for improvement in the library here. If you read the ip::tcp::iostream class (i.e. basic_socket_iostream<ip::tcp>), you'll see that it has two base classes:
private detail::socket_iostream_base<ip::tcp>
public std::basic_iostream<char>
The former contains a basic_socket_streambuf<ip::tcp> (a derived class of std::streambuf and basic_socket<ip::tcp>), whose address is passed to the latter at construction-time.
For the most part, basic_socket_streambuf<ip::tcp> performs the actual socket operations via its basic_socket<ip::tcp> base class. However, there is the connect_to_endpoints() member function that jumps the abstraction and calls several low-level functions from the detail::socket_ops namespace directly on socket().native_handle(). (This seems to have been introduced in Git commit b60e92b13e.) Those functions will only work on TCP sockets, even though the class is a template for any protocol.
Until I discovered this issue, my plan to integrate SSL support as a iostream/streambuf was to provide a ssl protocol class and a basic_socket<ssl> template specialization to wrap the existing ssl::context and ssl::stream<ip::tcp::socket> classes. Something like this (won't compile):
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/basic_socket.hpp>
#include <boost/asio/ssl.hpp>
namespace boost {
namespace asio {
namespace ip {
class ssl
: public tcp // for reuse (I'm lazy!)
{
public:
typedef basic_socket_iostream<ssl> iostream;
// more things as needed ...
};
} // namespace ip
template <>
class basic_socket<ip::ssl>
{
class SslContext
{
ssl::context ctx;
public:
SslContext() : ctx(ssl::context::sslv23_client)
{
ctx.set_options(ssl::context::default_workarounds);
ctx.set_default_verify_paths();
}
ssl::context & context() { return ctx; }
} sslContext;
ssl::stream<ip::tcp::socket> sslSocket;
public:
explicit basic_socket(const executor & ex)
: sslSocket(ex, sslContext.context())
{}
executor get_executor() noexcept
{
return sslSocket.lowest_layer().get_executor();
}
void connect(const ip::tcp::endpoint & endpoint_)
{
sslSocket.next_layer().connect(endpoint_);
sslSocket.lowest_layer().set_option(ip::tcp::no_delay(true));
sslSocket.set_verify_mode(ssl::verify_peer);
sslSocket.set_verify_callback(
ssl::rfc2818_verification("TODO: pass the domain here through the stream/streambuf somehow"));
sslSocket.handshake(ssl::stream<ip::tcp::socket>::client);
}
void close()
{
sslSocket.shutdown();
sslSocket.next_layer().close();
}
};
} // namespace asio
} // namespace boost
But due to the design issue I'll have to specialize basic_socket_streambuf<ip::ssl> as well, to avoid the detail::socket_ops routines. (I should also avoid injecting the ssl protocol class into the boost::asio::ip namespace, but that's a side concern.)
Haven't spent much time on this, but it seems doable. Fixing basic_socket_streambuf<>::connect_to_endpoints() first should help greatly.
This is not so much of a technical question, but rather a c++ design question.
Frequently it seems that I have to design programs which have to manage some a protocol which has some sort of connection, parsing stage and abstract view. Typically I try and design my programs with separation of concerns at the forefront.
I keep ending out with "stacks" of objects, a system sits ontop of a parser, which in turns sits ontop of a connection (often there are more layers). These objects then use member function calls to call a layer below it (Tx), and uses callbacks (std::function, usually) to capture information coming from the other directions (Rx).
This design seems really subpar, as it add complexity, and each layer has to have a progressively bigger constructor and so on. Also because the connection usually uses something like ASIO, the callbacks are generally on different threads so it's hard to reason about thread saftey.
Is there a design patterm, or idiom that represent this structure/functionality better?
EDIT
A simple example
class basic_connection {
basic_connection(std::string address);
void send(std::string);
std::function<void(std::string)> on_receive;
};
I have a few classes like this, which hold that layer's state, and are glue together by their public member functions and callbacks.
The layer above this, receives command data processes for the network and calls basic_connection::send. And takes the raw data from basic_connection and converts into commands for the layer above it unprocessed.
EDIT2:
Another issue that I forgot to mention is that you end up forwarding some of the interface though the stack, for example, a top layer still needs to know the connection status.
Without having a set of requirements it's hard to recommend anything. However, from the high level description in your question it seems that you might want to use the model-view-controller pattern, maybe in conjunction with others. Remember, design patterns are your friends and you're the one who decides if usage is appropriate and to what degree. Design pattern are very easy to abuse and it's happening all the time.
It sounds like what you are trying to do is what is normally refered to as "constructing a pipeline".
Here is one simple way to connect two layers:
class I
{
virtual void a() = 0;
virtual void b() = 0;
}
class X
{
I& m_i;
X(I& i) : m_i(i) {}
void onRecv(const char* data, size_t len)
{
for (size_t p = 0; p < len; p++)
switch (data[p])
{
case 'a': m_i.a(); break;
case 'b': m_i.b(); break;
}
}
}
class Y : public I
{
void a() { ... }
void b() { ... }
}
int main()
{
X x;
Y y(x);
while (...)
x.onRecv(data,len);
}
It seems to me that what you need is additional abstraction. I would begin by designing a general type to describe what a layer actually is and (if appropriate) refine that for each particular layer without taking into account your concrete protocols for these layers.
So, you could say a layer-k protocol needs an object of type layer-(k-1).
From your description I assume your higher layers are constructing their immediate lower layer which makes the constructors inflate. Simply ask for a reference (probably best implemented by a shared_ptr or unique_ptr) for the next lower layer in your constructor and have the interface user bother about its instantiation.
Since you defined an abstract interface, you can still use the lower layer polymorphically, without having to bother with how it's implemented and what particular lower layer protocol is used.
For reception, you typically need callbacks which can be implemented in the same fashion. You can even install these in the constructor of higher layer objects and remove them in the destructor.
If you know at design time which protocol will play with which other protocol, you could also replace the polymorphic calls by making your protocol implementation a template that receives its lower protocol something like this: Tcp<Ip<Ethernet<Device>>>.
I am in the process of starting to implement some proprietary communication protocol stack in software but not sure where to start. It is the kind of work I have not done before and I am looking for help in terms of resources for best/recommended approaches.
I will be using c/c++ and I am free to use use libraries (BSD/BOOST/Apache) but no GPL. I have used C++ extensively so using the features of C++ is not a problem.
The protocol stack has three layers and it is already fully specified and formally verified. So all I need to do is implemented and test it fully in the specified languages. Should also mention that protocol is very simple but can run on different devices over a reliable physical transport layer. I know the events, inputs, outputs, side effects and the behaviour of the protocol state machine(s). Generally, an interrupt is received to read the message received from the physical layer to read it and send to the waiting device. The receiving device can process and pass the response message to the protocol layer to send out on the physical layer.
Any help with references/recommendations will be appreciated. I am willing to use a different language if only to help me understand how to implement them but I will have to eventually resort to the language of choice.
Update: An example protocol I wish to implement is something like SNEP.
I do not need to worry about connection management. We can assume the connection is already establish and I the protocol does is data exchange where the protocol messages are already well defined in specifications
Start with interfaces and messages.
Declare the interfaces of session that allow peers to exchange messages. Declare the messages as C++ structs with simple types, like ints, doubles, std::string's and and std::vectors. For example:
// these are your protocol messages
struct HelloRequest {
uint32_t seq_no;
// more stuff
};
struct HelloResponse {
uint32_t seq_no;
// more stuff
};
// Session callback for received messages
struct SessionReceiver {
virtual void connected(Session*) = 0;
virtual void receive(Session* from, HelloRequest msg) = 0;
virtual void receive(Session* from, HelloResponse msg) = 0;
virtual void disconnected(Session*) = 0;
};
// Session interface to send messages
struct Session {
virtual void send(HelloRequest msg) = 0;
virtual void send(HelloResponse msg) = 0;
};
// this connects asynchronously and then calls SessionReceiver::connected() with a newly established session
struct SessionInitiator {
virtual void connect(SessionReceiver* cb, std::string peer) = 0;
};
// this accepts connections asynchronously and then calls SessionReceiver::connected() with a newly accepted session
struct SessionAcceptor {
virtual void listen(SessionReceiver* cb, std::string port) = 0;
};
Then test your interfaces by coding the business logic that uses these interfaces. Once you are confident that the interfaces allow you to implement the required logic implement the interfaces and serialization of your messages using your preferred event-driven framework, like libevent or Boost.Asio.
Edit:
Note that interfaces allow you to have mock or test implementations. Also the fact that serialization happens behind the interface means that for in-process peers you don't have to serialize and deserialize the messages, you can pass them as is.
Boost.ASIO is pretty cutting edge when it comes to Asynchronous (or synchronous) network communication in C++
Have a look at Google Protocol Buffers.
From the description:
Protocol buffers are a flexible, efficient, automated mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages. You can even update your data structure without breaking deployed programs that are compiled against the "old" format.
Protocol Buffers are language and platform neutral so should fit into your project. I couldn't find the license, but at least it doesn't say "GPL" anywhere that I could find.
This will help you with the protocols. With the actual data transmission, well, unless you are writing the OS yourself, there should be some primitives you should use. It's hard to give more exact help on implementation unless you provide a bit more detail. For instance, what communication channel are you using? Ethernet?
But as a rule of thumb, you should make the ISR as short as possible. In these kinds of solutions that usually means copying data to a ring buffer. This way you don't have to allocate memory in the ISR. ISR, after having copied the data, should inform upper layers of the package. If you can use DMA, use that. In that case it might be possible to send the notification before you even start the DMA transfer.
You might also want to check out Linux Device Drivers, chapter 10 in particular. Check out the part about Bottom and Top Halves.
I'm looking for a solution for this problem in C or C++.
edit: To clarify. This is on a linux system. Linux-specific solutions are absolutely fine. Cross-plaform is not a concern.
I have a service that runs in its own thread. This service is a class with several methods, some of which need to run in the own service's thread rather than in the caller's thread.
Currently I'm using wrapper methods that create a structure with input and output parameters, insert the structure on a queue and either return (if a "command" is asynchronous) or wait for its execution (if a "command" is synchronous).
On the thread side, the service wakes, pops a structure from the queue, figures out what to execute and calls the appropriate method.
This implementation works but adding new methods is quite cumbersome: define wrapper, structure with parameters, and handler. I was wondering if there is a more straightforward means of coding this kind of model: a class method that executes on the class's own thread, instead of in the caller's thread.
edit - kind of conclusion:
It seems that there's no de facto way to implement what I asked that doesn't involve extra coding effort.
I'll stick with what I came up with, it ensures type safeness, minimizes locking, allows sync and async calls and the overhead it fairly modest.
On the other hand it requires a bit of extra coding and the dispatch mechanism may become bloated as the number of methods increases. Registering the dispatch methods on construction, or having the wrappers do that work seem to solve the issue, remove a bit of overhead and also remove some code.
My standard reference for this problem is here.
Implementing a Thread-Safe Queue using Condition Variables
As #John noted, this uses Boost.Thread.
I'd be careful about the synchronous case you described here. It's easy to get perf problems if the producer (the sending thread) waits for a result from the consumer (the service thread). What happens if you get 1000 async calls, filling up the queue with a backlog, followed by a sync call from each of your producer threads? Your system will 'play dead' until the queue backlog clears, freeing up those sync callers. Try to decouple them using async only, if you can.
There are several ways to achieve this, depending upon the complexity you want to accept. Complexity of the code is directly proportional to the flexibility desired. Here's a simple one (and quite well used):
Define a classes corresponding to each functionality your server exposes.
Each of these classes implements a function called execute and take a basic structure called input args and output args.
Inside the service register these methods classes at the time of initialization.
Once a request comes to the thread, it will have only two args, Input and Ouput, Which are the base classes for more specialized arguments, required by different method classes.
Then you write you service class as mere delegation which takes the incoming request and passes on to the respective method class based on ID or the name of the method (used during initial registration).
I hope it make sense, a very good example of this approach is in the XmlRpc++ (a c++ implementation of XmlRpc, you can get the source code from sourceforge).
To recap:
struct Input {
virtual ~Input () = 0;
};
struct Ouput {
virtual ~Output () = 0;
};
struct MethodInterface {
virtual int32_t execute (Input* __input, Output* __output) = 0;
};
// Write specialized method classes and taking specialized input, output classes
class MyService {
void registerMethod (std::string __method_name, MethodInterface* __method);
//external i/f
int32_t execute (std::string __method, Input* __input, Output* __output);
};
You will still be using the queue mechanism, but you won't need any wrappers.
IMHO, If you want to decouple method execution and thread context, you should use Active Object Pattern (AOP)
However, you need to use ACE Framework, which supports many OSes, e.g. Windows, Linux, VxWorks
You can find detailed information here
Also, AOP is a combination of Command, Proxy and Observer Patterns, if you know the details of them, you may implement your own AOP. Hope it helps
In addition to using Boost.Thread, I would look at boost::function and boost::bind. That said, it seems fair to have untyped (void) arguments passed to the target methods, and let those methods cast to the correct type (a typical idiom for languages like C#).
Hey now Rajivji, I think you have it upside-down. Complexity of code is inversely proportional to flexibility. The more complex your data structures and algorithms are, the more restrictions you are placing on acceptable inputs and behaviour.
To the OP: your description seems perfectly general and the only solution, although there are different encodings of it. The simplest may be to derive a class from:
struct Xqt { virtual void xqt(){} virtual ~Xqt(){} };
and then have a thread-safe queue of pointers to Xqt. The service thread then just pops the queue to px and calls px->xqt(), and then delete px. The most important derived class is this one:
struct Dxqt : Xqt {
xqt *delegate;
Dxqt(xqt *d) : delegate(d) {}
void xqt() { delegate->xqt(); }
};
because "all problems in Computer Science can be solved by one more level of indirection" and in particular this class doesn't delete the delegate. This is much better than using a flag, for example, to determine if the closure object should be deleted by the server thread.