libzypp  17.35.14
stompframestream.h
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 -----------------------------------------------------------------------/
9 *
10 * This file contains private API, this might break at any time between releases.
11 * You have been warned!
12 *
13 */
14 
15 #ifndef ZYPP_CORE_ZYPPNG_RPC_STOMPFRAMESTREAM_H_INCLUDED
16 #define ZYPP_CORE_ZYPPNG_RPC_STOMPFRAMESTREAM_H_INCLUDED
17 
18 #include <zypp-core/TriBool.h>
19 #include <zypp-core/zyppng/base/Base>
20 #include <zypp-core/zyppng/core/String>
21 #include <zypp-core/zyppng/base/Signals>
22 #include <zypp-core/zyppng/base/Timer>
23 #include <zypp-core/zyppng/io/IODevice>
25 
27 
28 #include <deque>
29 #include <optional>
30 
31 namespace zyppng {
32 
33  ZYPP_FWD_DECL_TYPE_WITH_REFS (StompFrameStream);
34 
36  {
37  public:
38  InvalidMessageReceivedException( const std::string &msg = {});
39  };
40 
41  namespace rpc {
42 
43  template <typename T>
45  return msg.toStompMessage();
46  }
47 
48  template <typename T>
50  return T::fromStompMessage( message );
51  }
52 
53  // Reads data from the stomp message and converts it to the target type
54  // used to read header values and values serialized into a terminated data field
55  template <typename T>
56  void parseDataIntoField( const std::string &headerVal, T &target )
57  {
58  if constexpr ( std::is_same_v<bool, T> ) {
59  const auto &triBool = zypp::str::strToTriBool ( headerVal );
60  if ( indeterminate(triBool) ) {
61  ZYPP_THROW ( zypp::PluginFrameException( "Invalid value for boolean field" ) );
62  }
63  target = bool(triBool);
64  } else if constexpr ( std::is_same_v<std::string, T> ) {
65  target = headerVal;
66  } else {
67  // numbers
68  auto val = zyppng::str::safe_strtonum<T> ( headerVal );
69  if ( !val )
70  ZYPP_THROW ( zypp::PluginFrameException( "Invalid value for numerical field" ) );
71  target = *val;
72  }
73  }
74 
75  // queries a header value and calls parseDataIntoField on it
76  template <typename T>
77  void parseHeaderIntoField( const zypp::PluginFrame &msg, const std::string &name, T &target )
78  {
79  return parseDataIntoField ( msg.getHeader(name), target );
80  }
81 
82  template <typename T>
84  return zypp::PluginFrame ( std::string( T::typeName.data(), T::typeName.length() ) );
85  }
86 
87  }
88 
95  {
96  public:
97 
98  using Ptr = StompFrameStreamRef;
99 
105  static Ptr create( IODevice::Ptr iostr ) {
106  return Ptr( new StompFrameStream( std::move(iostr) ) );
107  }
108 
114  std::optional<zypp::PluginFrame> nextMessage ( const std::string &msgName = "" );
115 
124  std::optional<zypp::PluginFrame> nextMessageWait ( const std::string &msgName = "" );
125 
130  bool sendFrame ( const zypp::PluginFrame &message );
131 
132  template <typename T>
133  bool sendMessage ( const T &message )
134  {
135  if constexpr ( std::is_same_v<T, zypp::PluginFrame> ) {
136  return sendFrame( message );
137  } else {
138  const auto &msg = rpc::toStompMessage(message);
139  if ( !msg ) {
140  ERR << "Failed to serialize message" << std::endl;
141  return false;
142  }
143  return sendFrame( *msg );
144  }
145  }
146 
147  template<class T>
149  return rpc::fromStompMessage<T>(m);
150  }
151 
156  void readAllMessages ();
157 
162  SignalProxy<void()> sigMessageReceived ();
163 
167  SignalProxy<void()> sigInvalidMessageReceived ();
168 
169  private:
171  bool readNextMessage ();
172  void timeout( const zyppng::Timer &);
173 
174  enum ParserState {
178  ParseError
179  } _parserState = ReceiveCommand;
180 
181  std::optional<zypp::PluginFrame> _pendingMessage;
182  std::optional<int64_t> _pendingBodyLen;
183 
185  Timer::Ptr _nextMessageTimer = Timer::create();
186  std::deque<zypp::PluginFrame> _messages;
189 
190  };
191 }
192 
193 #endif // ZYPP_CORE_ZYPPNG_RPC_STOMPFRAMESTREAM_H_INCLUDED
expected< zypp::PluginFrame > toStompMessage(const T &msg)
static Ptr create(IODevice::Ptr iostr)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:424
Command frame for communication with PluginScript.
Definition: PluginFrame.h:41
#define ZYPP_API
Definition: Globals.h:69
Signal< void()> _sigNextMessage
#define ERR
Definition: Logger.h:102
bool sendMessage(const T &message)
expected< T > fromStompMessage(const zypp::PluginFrame &message)
TriBool strToTriBool(const C_Str &str)
Parse str into a bool if it&#39;s a legal true or false string; else indeterminate.
Definition: String.cc:94
ZYPP_FWD_DECL_TYPE_WITH_REFS(Context)
void parseDataIntoField(const std::string &headerVal, T &target)
Base class for PluginFrame Exception.
std::optional< int64_t > _pendingBodyLen
The Timer class provides repetitive and single-shot timers.
Definition: timer.h:44
zypp::PluginFrame prepareFrame()
std::shared_ptr< IODevice > Ptr
Definition: iodevice.h:45
std::optional< zypp::PluginFrame > _pendingMessage
std::shared_ptr< Timer > Ptr
Definition: timer.h:51
static std::shared_ptr< Timer > create()
Creates a new Timer object, the timer is not started at this point.
Definition: timer.cc:52
Base class for Exception.
Definition: Exception.h:146
Signal< void()> _sigInvalidMessageReceived
void parseHeaderIntoField(const zypp::PluginFrame &msg, const std::string &name, T &target)
const std::string & getHeader(const std::string &key_r) const
Return header value for key_r.
Definition: PluginFrame.cc:469
static expected< T > parseMessage(const zypp::PluginFrame &m)
std::shared_ptr< Base > Ptr
Definition: base.h:65
std::deque< zypp::PluginFrame > _messages