ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
RebotDummyServer.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3#pragma once
4
5#include "DummyBackend.h"
7
8#include <boost/asio.hpp>
9
10#include <atomic>
11#include <memory>
12#include <string>
13
14namespace ip = boost::asio::ip;
15
16namespace ChimeraTK {
17
18 extern std::atomic<bool> stop_rebot_server;
19
20 /*
21 * starts a blocking Rebot server on localhost:port. where port is the
22 * portNumber specified during object creation.
23 */
24 class RebotDummySession : public std::enable_shared_from_this<RebotDummySession> {
25 // everything is public so all protocol implementors can reach it. They are
26 // only called from within the server
27 public:
29 unsigned int protocolVersion, ip::tcp::socket socket, std::shared_ptr<DummyBackend> regsiterSpace);
30 void start();
31 virtual ~RebotDummySession();
32
33 // The following stuff is only intended for the protocol implementors and the
34 // server itself
35
36 static const int BUFFER_SIZE_IN_WORDS = 256;
37 static const int32_t READ_SUCCESS_INDICATION = 1000;
38 static const int32_t WRITE_SUCCESS_INDICATION = 1001;
39 static const uint32_t PONG = 1005;
40 static const int32_t TOO_MUCH_DATA_REQUESTED = -1010;
41 static const int32_t UNKNOWN_INSTRUCTION = -1040;
42
43 static const uint32_t SINGLE_WORD_WRITE = 1;
44 static const uint32_t MULTI_WORD_WRITE = 2;
45 static const uint32_t MULTI_WORD_READ = 3;
46 static const uint32_t HELLO = 4;
47 static const uint32_t PING = 5;
48 static const uint32_t REBOT_MAGIC_WORD = 0x72626f74; // ascii code 'rbot'
49
50 // internal states. Currently there are only two when the connection is open
51 static const uint32_t ACCEPT_NEW_COMMAND = 1;
52 // a multi word write can be so large that it needs more than one package
53 static const uint32_t INSIDE_MULTI_WORD_WRITE = 2;
54
55 // The actual state: ready for new command or not
56 uint32_t _state;
57
58 std::atomic<uint32_t> _heartbeatCount;
59 std::atomic<uint32_t> _helloCount; // in protocol version 1 we have to send
60 // hello instead of heartbeat
61 std::atomic<bool> _dont_answer; // flag to cause an error condition
62 std::shared_ptr<DummyBackend> _registerSpace;
63 std::vector<uint32_t> _dataBuffer;
64
65 unsigned int _serverPort;
66 unsigned int _protocolVersion;
67 ip::tcp::socket _currentClientConnection;
68 std::unique_ptr<DummyProtocolImplementor> _protocolImplementor;
69
70 void processReceivedPackage(std::vector<uint32_t>& buffer);
71 void writeWordToRequestedAddress(std::vector<uint32_t>& buffer);
72 void readRegisterAndSendData(std::vector<uint32_t>& buffer);
73
74 // most commands have a single word as response. Avoid code duplication.
75 void sendSingleWord(int32_t response);
76 void acceptHandler(const boost::system::error_code& error);
77 void doRead();
78 void doWrite();
79 void write(std::vector<uint32_t> data);
80 };
81
83 public:
84 RebotDummyServer(unsigned int portNumber, std::string mapFile, unsigned int protocolVersion);
85
86 void start();
87 void stop();
88 bool is_running();
89 unsigned int port() const { return _connectionAcceptor.local_endpoint().port(); }
90
91 boost::asio::io_context& service() { return _io; }
92 std::shared_ptr<RebotDummySession> session() { return _currentSession.lock(); }
93
94 private:
95 void do_accept();
96 unsigned int _protocolVersion;
97 boost::asio::io_context _io;
98 ip::tcp::acceptor _connectionAcceptor;
99 std::weak_ptr<RebotDummySession> _currentSession;
100 ip::tcp::socket _socket;
101 std::shared_ptr<DummyBackend> _registerSpace;
102 };
103
104} /* namespace ChimeraTK */
unsigned int port() const
boost::asio::io_context & service()
std::shared_ptr< RebotDummySession > session()
void acceptHandler(const boost::system::error_code &error)
static const int32_t TOO_MUCH_DATA_REQUESTED
static const int32_t WRITE_SUCCESS_INDICATION
static const uint32_t INSIDE_MULTI_WORD_WRITE
std::atomic< uint32_t > _heartbeatCount
static const uint32_t MULTI_WORD_WRITE
ip::tcp::socket _currentClientConnection
void writeWordToRequestedAddress(std::vector< uint32_t > &buffer)
void processReceivedPackage(std::vector< uint32_t > &buffer)
static const uint32_t ACCEPT_NEW_COMMAND
std::vector< uint32_t > _dataBuffer
static const uint32_t HELLO
std::atomic< uint32_t > _helloCount
void sendSingleWord(int32_t response)
void readRegisterAndSendData(std::vector< uint32_t > &buffer)
static const uint32_t PING
static const uint32_t PONG
static const uint32_t MULTI_WORD_READ
static const int32_t READ_SUCCESS_INDICATION
std::unique_ptr< DummyProtocolImplementor > _protocolImplementor
static const int BUFFER_SIZE_IN_WORDS
static const int32_t UNKNOWN_INSTRUCTION
static const uint32_t SINGLE_WORD_WRITE
std::shared_ptr< DummyBackend > _registerSpace
std::atomic< bool > _dont_answer
static const uint32_t REBOT_MAGIC_WORD
std::atomic< bool > stop_rebot_server