Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
asn1_message.h
1 #ifndef ASN1_MESSAGE_H_
2 #define ASN1_MESSAGE_H_
3 #include <boost/intrusive_ptr.hpp>
4 
5 #include "AKIpUptaneMes.h"
6 #include "AKTlsConfig.h"
7 
8 class Asn1Message;
9 
10 template <typename T>
11 class Asn1Sub {
12  public:
13  Asn1Sub(boost::intrusive_ptr<Asn1Message> root, T* me) : root_(std::move(root)), me_(me) {}
14 
15  T& operator*() const {
16  assert(me_ != nullptr);
17  return *me_;
18  }
19 
20  T* operator->() const {
21  assert(me_ != nullptr);
22  return me_;
23  }
24 
25  private:
26  boost::intrusive_ptr<Asn1Message> root_;
27  T* me_;
28 };
29 
30 /**
31  * Reference counted holder for the top-level ASN1 message structure.
32  */
33 
34 class Asn1Message {
35  public:
36  using Ptr = boost::intrusive_ptr<Asn1Message>;
37  template <typename T>
38  using SubPtr = Asn1Sub<T>;
39 
40  Asn1Message(const Asn1Message&) = delete;
41  Asn1Message operator=(const Asn1Message&) = delete;
42 
43  /**
44  * Create a new Asn1Message, in order to fill it with data and send it
45  */
46  static Asn1Message::Ptr Empty() { return new Asn1Message(); }
47 
48  /**
49  * Destructively copy from a raw msg pointer created by parsing an incomming
50  * message. This takes ownership of the contents of the message, and sets
51  * *msg=nullptr to make this fact clear.
52  */
53  static Asn1Message::Ptr FromRaw(AKIpUptaneMes_t** msg) { return new Asn1Message(msg); }
54 
55  ~Asn1Message() { ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_AKIpUptaneMes, &msg_); }
56  friend void intrusive_ptr_add_ref(Asn1Message* m) { m->ref_count_++; }
57  friend void intrusive_ptr_release(Asn1Message* m) {
58  if (--m->ref_count_ == 0) {
59  delete m;
60  }
61  }
62 
63  AKIpUptaneMes_PR present() const { return msg_.present; }
64  Asn1Message& present(AKIpUptaneMes_PR present) {
65  msg_.present = present;
66  return *this;
67  }
68 
69 #define ASN1_MESSAGE_DEFINE_ACCESSOR(MessageType, FieldName) \
70  SubPtr<MessageType> FieldName() { \
71  return Asn1Sub<MessageType>(this, &msg_.choice.FieldName); /* NOLINT(cppcoreguidelines-pro-type-union-access) */ \
72  }
73 
74  ASN1_MESSAGE_DEFINE_ACCESSOR(AKGetInfoReqMes_t, getInfoReq);
75  ASN1_MESSAGE_DEFINE_ACCESSOR(AKGetInfoRespMes_t, getInfoResp);
76  ASN1_MESSAGE_DEFINE_ACCESSOR(AKManifestReqMes_t, manifestReq);
77  ASN1_MESSAGE_DEFINE_ACCESSOR(AKManifestRespMes_t, manifestResp);
78  ASN1_MESSAGE_DEFINE_ACCESSOR(AKPutMetaReqMes_t, putMetaReq);
79  ASN1_MESSAGE_DEFINE_ACCESSOR(AKPutMetaRespMes_t, putMetaResp);
80  ASN1_MESSAGE_DEFINE_ACCESSOR(AKSendFirmwareReqMes_t, sendFirmwareReq);
81  ASN1_MESSAGE_DEFINE_ACCESSOR(AKSendFirmwareRespMes_t, sendFirmwareResp);
82  ASN1_MESSAGE_DEFINE_ACCESSOR(AKInstallReqMes_t, installReq);
83  ASN1_MESSAGE_DEFINE_ACCESSOR(AKInstallRespMes_t, installResp);
84 
85 #define ASN1_MESSAGE_DEFINE_STR_NAME(MessageID) \
86  case MessageID: \
87  return #MessageID;
88 
89  const char* toStr() {
90  switch (present()) {
91  default:
92  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_NOTHING);
93  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_getInfoReq);
94  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_getInfoResp);
95  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_manifestReq);
96  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_manifestResp);
97  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_putMetaReq);
98  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_putMetaResp);
99  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_sendFirmwareReq);
100  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_sendFirmwareResp);
101  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_installReq);
102  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_installResp);
103  }
104  return "Unknown";
105  };
106 
107  /**
108  * The underlying message structure. This is public to simplify calls to
109  * der_encode()/der_decode(). The Asn1<T> smart pointers should be used
110  * in preference to poking around inside msg_.
111  */
112  AKIpUptaneMes_t msg_{}; // Note that this must be zero-initialized
113 
114  private:
115  int ref_count_{0};
116 
117  Asn1Message() = default;
118 
119  explicit Asn1Message(AKIpUptaneMes_t** msg) {
120  if (msg != nullptr && *msg != nullptr) {
121  memmove(&msg_, *msg, sizeof(AKIpUptaneMes_t));
122  free(*msg); // Be careful. This needs to be the same free() used in der_decode
123  *msg = nullptr;
124  }
125  }
126 };
127 
128 /**
129  * Adaptor to write output of der_encode to a string
130  */
131 int Asn1StringAppendCallback(const void* buffer, size_t size, void* priv);
132 
133 /**
134  * Adaptor to write output of der_encode to a socket
135  * priv is a pointer to an int holding the fd
136  */
137 int Asn1SocketWriteCallback(const void* buffer, size_t size, void* priv);
138 
139 /**
140  * Convert OCTET_STRING_t into std::string
141  */
142 std::string ToString(const OCTET_STRING_t& octet_str);
143 
144 void SetString(OCTET_STRING_t* dest, const std::string& str);
145 
146 /**
147  * Open a TCP connection to client; send a message and wait for a
148  * response.
149  */
150 Asn1Message::Ptr Asn1Rpc(const Asn1Message::Ptr& tx, int con_fd);
151 Asn1Message::Ptr Asn1Rpc(const Asn1Message::Ptr& tx, const std::pair<std::string, uint16_t>& addr);
152 #endif // ASN1_MESSAGE_H_
static Asn1Message::Ptr FromRaw(AKIpUptaneMes_t **msg)
Destructively copy from a raw msg pointer created by parsing an incomming message.
Definition: asn1_message.h:53
static Asn1Message::Ptr Empty()
Create a new Asn1Message, in order to fill it with data and send it.
Definition: asn1_message.h:46
Reference counted holder for the top-level ASN1 message structure.
Definition: asn1_message.h:34