Aktualizr
C++ SOTA Client
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  ASN1_MESSAGE_DEFINE_ACCESSOR(AKUploadDataReqMes_t, uploadDataReq);
86  ASN1_MESSAGE_DEFINE_ACCESSOR(AKUploadDataRespMes_t, uploadDataResp);
87  ASN1_MESSAGE_DEFINE_ACCESSOR(AKDownloadOstreeRevReqMes_t, downloadOstreeRevReq);
88  ASN1_MESSAGE_DEFINE_ACCESSOR(AKDownloadOstreeRevRespMes_t, downloadOstreeRevResp);
89  ASN1_MESSAGE_DEFINE_ACCESSOR(AKPutMetaReq2Mes_t, putMetaReq2);
90  ASN1_MESSAGE_DEFINE_ACCESSOR(AKPutMetaResp2Mes_t, putMetaResp2);
91  ASN1_MESSAGE_DEFINE_ACCESSOR(AKInstallResp2Mes_t, installResp2);
92  ASN1_MESSAGE_DEFINE_ACCESSOR(AKVersionReqMes_t, versionReq);
93  ASN1_MESSAGE_DEFINE_ACCESSOR(AKVersionRespMes_t, versionResp);
94 
95 #define ASN1_MESSAGE_DEFINE_STR_NAME(MessageID) \
96  case MessageID: \
97  return #MessageID;
98 
99  const char* toStr() {
100  switch (present()) {
101  default:
102  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_NOTHING);
103  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_getInfoReq);
104  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_getInfoResp);
105  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_manifestReq);
106  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_manifestResp);
107  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_putMetaReq);
108  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_putMetaResp);
109  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_sendFirmwareReq);
110  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_sendFirmwareResp);
111  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_installReq);
112  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_installResp);
113 
114  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_uploadDataReq);
115  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_uploadDataResp);
116  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_downloadOstreeRevReq);
117  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_downloadOstreeRevResp);
118  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_putMetaReq2);
119  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_putMetaResp2);
120  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_installResp2);
121  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_versionReq);
122  ASN1_MESSAGE_DEFINE_STR_NAME(AKIpUptaneMes_PR_versionResp);
123  }
124  return "Unknown";
125  };
126 
127  /**
128  * The underlying message structure. This is public to simplify calls to
129  * der_encode()/der_decode(). The Asn1<T> smart pointers should be used
130  * in preference to poking around inside msg_.
131  */
132  AKIpUptaneMes_t msg_{}; // Note that this must be zero-initialized
133 
134  private:
135  int ref_count_{0};
136 
137  Asn1Message() = default;
138 
139  explicit Asn1Message(AKIpUptaneMes_t** msg) {
140  if (msg != nullptr && *msg != nullptr) {
141  memmove(&msg_, *msg, sizeof(AKIpUptaneMes_t));
142  free(*msg); // Be careful. This needs to be the same free() used in der_decode
143  *msg = nullptr;
144  }
145  }
146 };
147 
148 /**
149  * Adaptor to write output of der_encode to a string
150  */
151 int Asn1StringAppendCallback(const void* buffer, size_t size, void* priv);
152 
153 /**
154  * Adaptor to write output of der_encode to a socket
155  * priv is a pointer to an int holding the fd
156  */
157 int Asn1SocketWriteCallback(const void* buffer, size_t size, void* priv);
158 
159 /**
160  * Convert OCTET_STRING_t into std::string
161  */
162 std::string ToString(const OCTET_STRING_t& octet_str);
163 
164 void SetString(OCTET_STRING_t* dest, const std::string& str);
165 
166 /**
167  * Open a TCP connection to client; send a message and wait for a
168  * response.
169  */
170 Asn1Message::Ptr Asn1Rpc(const Asn1Message::Ptr& tx, int con_fd);
171 Asn1Message::Ptr Asn1Rpc(const Asn1Message::Ptr& tx, const std::pair<std::string, uint16_t>& addr);
172 
173 /*
174  * Helper function for creating pointers to ASN.1 types. Note that the encoder
175  * will free these objects for you.
176  */
177 template <typename T>
178 T* Asn1Allocation() {
179  auto ptr = static_cast<T*>(calloc(1, sizeof(T)));
180  if (!ptr) {
181  throw std::bad_alloc();
182  }
183  return ptr;
184 }
185 
186 #endif // ASN1_MESSAGE_H_
Asn1Message::Empty
static Asn1Message::Ptr Empty()
Create a new Asn1Message, in order to fill it with data and send it.
Definition: asn1_message.h:46
Asn1Message
Reference counted holder for the top-level ASN1 message structure.
Definition: asn1_message.h:34
Asn1Message::FromRaw
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
Asn1Sub
Definition: asn1_message.h:11
Asn1Message::msg_
AKIpUptaneMes_t msg_
The underlying message structure.
Definition: asn1_message.h:132