|
| 1 | +/** |
| 2 | + * @file |
| 3 | + * @author Pavel Siska <[email protected]> |
| 4 | + * @brief Defines a bidirectional interface for sending and receiving unirec records using the TRAP |
| 5 | + * interface provided by the UniRec library. This class provides a simple and easy-to-use |
| 6 | + * bidirectional interface for sending and receiving unirec records with the SAME format. It wraps |
| 7 | + * the TRAP interface provided by the UniRec library and includes methods for sending and receiving |
| 8 | + * records, changing the record template, setting timeouts, and more. |
| 9 | + * |
| 10 | + * SPDX-License-Identifier: BSD-3-Clause |
| 11 | + */ |
| 12 | + |
| 13 | +#pragma once |
| 14 | + |
| 15 | +#include "unirecException.hpp" |
| 16 | +#include "unirecRecord.hpp" |
| 17 | +#include "unirecRecordView.hpp" |
| 18 | + |
| 19 | +#include <optional> |
| 20 | +#include <stdexcept> |
| 21 | +#include <string> |
| 22 | +#include <unirec/unirec.h> |
| 23 | + |
| 24 | +namespace NemeaPlusPlus { |
| 25 | + |
| 26 | +/** |
| 27 | + * @brief A class that provides a bidirectional interface for sending and receiving unirec records. |
| 28 | + * |
| 29 | + * This class wraps the TRAP interface provided by the UniRec library to provide a simple |
| 30 | + * and easy-to-use bidirectional interface for sending and receiving unirec records with the SAME |
| 31 | + * FORMAT. |
| 32 | + */ |
| 33 | +class UnirecBidirectionalInterface { |
| 34 | +public: |
| 35 | + /** |
| 36 | + * @brief Receives data from the interface and returns an optional UnirecRecordView object. |
| 37 | + * |
| 38 | + * If data is received successfully, an UnirecRecordView object is returned that provides a view |
| 39 | + * into the received data. If no data is available or a timeout occurs, std::nullopt is |
| 40 | + * returned. |
| 41 | + * |
| 42 | + * @return An optional UnirecRecordView object. |
| 43 | + * @throws EoFException if the end of the input stream is reached. |
| 44 | + * @throws FormatChangeException if the record format changes. |
| 45 | + */ |
| 46 | + std::optional<UnirecRecordView> receive(); |
| 47 | + |
| 48 | + /** |
| 49 | + * @brief Sends a UniRec record through the Trap interface. |
| 50 | + * |
| 51 | + * @param unirecRecord the Unirec record to send |
| 52 | + * @throws std::runtime_error if an error occurs while sending the record |
| 53 | + * @return true if the record was sent successfully, false if a timeout occurred |
| 54 | + */ |
| 55 | + bool send(UnirecRecord& unirecRecord) const; |
| 56 | + |
| 57 | + /** |
| 58 | + * @brief Sends a UniRec record view through the Trap interface. |
| 59 | + * |
| 60 | + * @param unirecRecordView The UniRec record view to send. |
| 61 | + * @throws std::runtime_error if an error occurs while sending the record |
| 62 | + * @return true if the record was sent successfully, false if a timeout occurred |
| 63 | + */ |
| 64 | + bool send(UnirecRecordView& unirecRecordView) const; |
| 65 | + |
| 66 | + /** |
| 67 | + * @brief Flushes any pending UniRec records in the Trap interface. |
| 68 | + */ |
| 69 | + void sendFlush() const; |
| 70 | + |
| 71 | + /** |
| 72 | + * @brief Changes the Unirec template used by the bidirectional interface. |
| 73 | + * |
| 74 | + * This method should be called every time when the FormatChangeException is thrown. |
| 75 | + * |
| 76 | + * This method changes the UniRec record template used for decoding records received on the |
| 77 | + * interface. |
| 78 | + * |
| 79 | + * @throws std::runtime_error if the data format was not loaded or the template could not be |
| 80 | + * edited. |
| 81 | + */ |
| 82 | + void changeTemplate(); |
| 83 | + |
| 84 | + /** |
| 85 | + * @brief Sets the required Unirec format specification. |
| 86 | + * |
| 87 | + * This method sets the required Unirec format specification for the input interface. |
| 88 | + * Format: "uint64 BYTES, string SNI" (unirecDataType NAME) |
| 89 | + * |
| 90 | + * @param templateSpecification The required Unirec format specification. |
| 91 | + * @throws std::runtime_error if the required format could not be set. |
| 92 | + */ |
| 93 | + void setRequieredFormat(const std::string& templateSpecification); |
| 94 | + |
| 95 | + /** |
| 96 | + * @brief Sets the receive timeout for the interface. |
| 97 | + * This method sets the timeout for receiving UniRec records on the interface. If no record is |
| 98 | + * received within the specified timeout, the receive method returns an empty optional. |
| 99 | + * |
| 100 | + * @param timeout The timeout value in microseconds. |
| 101 | + * - `TRAP_WAIT`: Blocking mode, wait for client's connection, for message transport to/from |
| 102 | + * internal system buffer. |
| 103 | + * - `TRAP_NO_WAIT`: Non-Blocking mode, do not wait ever. |
| 104 | + * - `timeout`: Wait max for specific time. |
| 105 | + */ |
| 106 | + void setReceiveTimeout(int timeout); |
| 107 | + |
| 108 | + /** |
| 109 | + * @brief Sets the send timeout for the Trap interface. |
| 110 | + * |
| 111 | + * @param timeout The timeout value in microseconds. |
| 112 | + * - `TRAP_WAIT`: Blocking mode, wait for client's connection, for message transport |
| 113 | + * to/from internal system buffer. |
| 114 | + * - `TRAP_HALFWAIT`: Blocking only if any client is connected. |
| 115 | + * - `TRAP_NO_WAIT`: Non-Blocking mode, do not wait ever. |
| 116 | + * - `timeout`: Wait max for specific time. |
| 117 | + */ |
| 118 | + void setSendTimeout(int timeout); |
| 119 | + |
| 120 | + /** |
| 121 | + * @brief Sets the autoflush timeout for the output Trap interface. |
| 122 | + * |
| 123 | + * @param timeout The timeout value in microseconds. |
| 124 | + * - `TRAP_NO_AUTO_FLUSH`: Do not autoflush trap buffers |
| 125 | + */ |
| 126 | + void setSendAutoflushTimeout(int timeout); |
| 127 | + |
| 128 | + /** |
| 129 | + * @brief Disables sending an end-of-file marker on exit. |
| 130 | + */ |
| 131 | + void doNotsendEoFOnExit(); |
| 132 | + |
| 133 | + /** |
| 134 | + * @brief Gets the Unirec template used by the bidirectional interface. |
| 135 | + * |
| 136 | + * This method returns a pointer to the Unirec template used by the bidirectional interface. |
| 137 | + * |
| 138 | + * @return A pointer to the Unirec template used by the bidirectional interface. |
| 139 | + */ |
| 140 | + ur_template_t* getTemplate() const noexcept { return m_template; } |
| 141 | + |
| 142 | + /** |
| 143 | + * @brief Destructor for the UnirecBidirectionalInterface class. |
| 144 | + * |
| 145 | + * Sends an end-of-file marker if m_sendEoFonExit is true, then frees the memory allocated |
| 146 | + * for the UniRec template. |
| 147 | + */ |
| 148 | + ~UnirecBidirectionalInterface(); |
| 149 | + |
| 150 | + /** |
| 151 | + * @brief Gets a reference to the pre-allocated UniRec record for efficient use. |
| 152 | + * |
| 153 | + * This function provides access to the UniRec record instance that has already been |
| 154 | + * pre-allocated within the UnirecOutputInterface. It allows direct modification of the |
| 155 | + * record's fields before sending it through the TRAP interface. Using the pre-allocated record |
| 156 | + * can be faster compared to creating a new record, as there is no memory allocation involved. |
| 157 | + * However, please note that using the same record in a multithreaded context may not be |
| 158 | + * thread-safe. |
| 159 | + * |
| 160 | + * @note The record accessed through this function is specific to this instance of the |
| 161 | + * UnirecOutputInterface and should not be shared across multiple instances or threads. |
| 162 | + * |
| 163 | + * @return A reference to the pre-allocated UniRec record. |
| 164 | + */ |
| 165 | + UnirecRecord& getUnirecRecord() noexcept { return m_unirecRecord; } |
| 166 | + |
| 167 | + /** |
| 168 | + * @brief Creates a new UniRec record with the specified maximum variable fields size. |
| 169 | + * |
| 170 | + * This function generates a fresh UniRec record instance, ready to be populated with data |
| 171 | + * before sending it through the TRAP interface. The maximum size of variable fields can be |
| 172 | + * specified to suit your data insertion needs. Unlike using the pre-allocated record with the |
| 173 | + * `getUnirecRecord` function, this function involves memory allocation and may have a slightly |
| 174 | + * higher overhead. |
| 175 | + * |
| 176 | + * @param maxVariableFieldsSize The maximum size for variable fields in the new UniRec record. |
| 177 | + * @return A newly created UnirecRecord instance. |
| 178 | + */ |
| 179 | + UnirecRecord createUnirecRecord(size_t maxVariableFieldsSize = UR_MAX_SIZE); |
| 180 | + |
| 181 | +private: |
| 182 | + UnirecBidirectionalInterface(uint8_t inputInterfaceID, uint8_t outputInterfaceID); |
| 183 | + void handleReceiveErrorCodes(int errorCode) const; |
| 184 | + bool handleSendErrorCodes(int errorCode) const; |
| 185 | + bool isEoFReceived() const noexcept; |
| 186 | + void sendEoF() const; |
| 187 | + |
| 188 | + ur_template_t* m_template; |
| 189 | + uint8_t m_inputInterfaceID; |
| 190 | + uint8_t m_outputInterfaceID; |
| 191 | + const void* m_prioritizedDataPointer; |
| 192 | + bool m_sendEoFonExit; |
| 193 | + bool m_EoFOnNextReceive; |
| 194 | + UnirecRecord m_unirecRecord; |
| 195 | + |
| 196 | + friend class Unirec; |
| 197 | +}; |
| 198 | + |
| 199 | +} // namespace NemeaPlusPlus |
0 commit comments