1 /* Copyright (c) 2014, 2021, Oracle and/or its affiliates. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 #ifndef GCS_GCS_MESSAGE_INCLUDED 24 #define GCS_GCS_MESSAGE_INCLUDED 25 26 #include "gcs_group_identifier.h" 27 #include "gcs_member_identifier.h" 28 #include "gcs_types.h" 29 30 #include <stdint.h> 31 #include <vector> 32 #include <cstring> 33 34 #define WIRE_PAYLOAD_LEN_SIZE 8 35 #define WIRE_HEADER_LEN_SIZE 4 36 37 /** 38 @class Gcs_message_data 39 40 This class serves as data container for information flowing in the GCS 41 ecosystem. It has been isolated in order to be used in place where a 42 full-blown Gcs_message does not make sense. 43 44 For a full usage example, check the Gcs_message documentation. 45 */ 46 class Gcs_message_data 47 { 48 public: 49 /** 50 Constructor of Gcs_message_data which pre-allocates space to store 51 the header and payload and should be used when creating messages to 52 send information to remote peers. 53 54 @param header_capacity Determines the header's size. 55 @param header_capacity Determines the payload's size. 56 */ 57 explicit Gcs_message_data(const uint32_t header_capacity, 58 const uint64_t payload_capacity); 59 60 /** 61 Constructor of Gcs_message_data which pre-allocates space to store 62 a message received from a remote peer. 63 64 @param data_len Data's length. 65 */ 66 explicit Gcs_message_data(const uint64_t data_len); 67 68 69 virtual ~Gcs_message_data(); 70 71 72 /** 73 Appends data to the header of the message. The data MUST have been 74 previously encoded in little endian format. 75 76 If the data to be appended exceeds the pre-allocated buffer capacity 77 an error is returned. 78 79 @param[in] to_append the data to append 80 @param[in] to_append_len the length of the data to append 81 82 @return true on error, false otherwise. 83 */ 84 85 bool append_to_header(const uchar *to_append, uint32_t to_append_len); 86 87 88 /** 89 Appends data to the payload of the message. The data MUST have been 90 previously encoded in little endian format. 91 92 If the data to be appended exceeds the pre-allocated buffer capacity 93 an error is returned. 94 95 @param[in] to_append the data to append 96 @param[in] to_append_len the length of the data to append 97 98 @return true on error, false otherwise. 99 */ 100 101 bool append_to_payload(const uchar *to_append, uint64_t to_append_len); 102 103 104 /** 105 Release the buffer's owership which means that this object will not 106 be responsible for deallocating its internal buffer. The caller should 107 do so. 108 109 This method should be used along with the following method: 110 encode(**buffer, *buffer_len). 111 **/ 112 113 void release_ownership(); 114 115 /** 116 Encodes the header and payload into an internal buffer. If NULL pointer 117 is provided or the data was not already appended to the buffer, an error 118 is returned. 119 120 The meta data is formated in little endian format, and is structured 121 on the wire as depicted below: 122 123 ----------------------------------------------- 124 | header len | payload len | header | payload | 125 ----------------------------------------------- 126 127 @param[in/out] Variable that will hold a pointer to the buffer 128 @param[in/out] Variable that will hold the buffer's size. 129 130 @return true on error, false otherwise. 131 */ 132 133 bool encode(uchar **buffer, uint64_t *buffer_len); 134 135 136 /** 137 Encodes the header and payload into a buffer provided by the caller. 138 If the buffer is not large enough to store the encoded data or is a 139 NULL pointer, an error is returned. 140 141 @param buffer[in/out] Buffer to store the encoded data in the message. 142 @param length[in/out] The length of the buffer where the data is to be stored. 143 It contains the length of the data dumped into the buffer once the function 144 succeeds. 145 146 @return true on error, false otherwise. 147 */ 148 149 bool encode(uchar *buffer, uint64_t *buffer_len); 150 151 152 /** 153 Decodes data received via GCS and that belongs to a message. After 154 decoding, all the fields will be filled. The data MUST be in little endian 155 format. 156 157 If the buffer is not large enough to store the encoded data or is a 158 NULL pointer, an error is returned. 159 160 @param[in] data Data received via network 161 @param[in] data_len Data length received via network 162 163 @return true on error, false otherwise. 164 */ 165 166 bool decode(const uchar *data, uint64_t data_len); 167 168 /** 169 @return the message header in little endian format 170 */ 171 172 const uchar *get_header() const; 173 174 175 /** 176 @return the message header length 177 */ 178 179 uint32_t get_header_length() const; 180 181 182 /** 183 @return the message payload in little endian format 184 */ 185 186 const uchar *get_payload() const; 187 188 189 /** 190 @return the message payload_length 191 */ 192 193 uint64_t get_payload_length() const; 194 195 196 /** 197 @return the size of the encoded data when put on the wire. 198 */ 199 200 uint64_t get_encode_size() const; 201 202 203 /** 204 @return the size of the encoded payload when put on the wire. 205 */ 206 207 uint64_t get_encode_payload_size() const; 208 209 210 /** 211 @return the size of the encoded header when put on the wire. 212 */ 213 214 uint64_t get_encode_header_size() const; 215 216 private: 217 /* 218 Pointer to the header's buffer. 219 */ 220 uchar *m_header; 221 222 /* 223 Pointer to the next empty position in the header's buffer. 224 */ 225 uchar *m_header_slider; 226 227 /* 228 Length of the header's buffer in use. 229 */ 230 uint32_t m_header_len; 231 232 /* 233 Capacity of the header's buffer. 234 */ 235 uint32_t m_header_capacity; 236 237 /* 238 Pointer to the payload's buffer. 239 */ 240 uchar *m_payload; 241 242 /* 243 Pointer to the next empty position in the payload's buffer. 244 */ 245 uchar *m_payload_slider; 246 247 /* 248 Length of the payload's buffer in use. 249 */ 250 uint64_t m_payload_len; 251 252 /* 253 Capacity of the header's buffer. 254 */ 255 uint64_t m_payload_capacity; 256 257 /* 258 Pointer to the begining of the buffer that contains both the 259 header and the payload. 260 */ 261 uchar *m_buffer; 262 263 /* 264 Length of the buffer that contains both the header, the 265 payload and metadata information. 266 */ 267 uint64_t m_buffer_len; 268 269 /* 270 Whether the current object owns the buffer and must free it 271 when deleted. 272 */ 273 bool m_owner; 274 275 /* 276 Disabling the copy constructor and assignment operator. 277 */ 278 Gcs_message_data(Gcs_message_data const&); 279 Gcs_message_data& operator=(Gcs_message_data const&); 280 }; 281 282 283 /** 284 @class Gcs_message 285 286 Class that represents the data that is exchanged within a group. It is sent 287 by a member having the group as destination. It shall be received by all 288 members that pertain to the group in that moment. 289 290 It is built using two major blocks: the header and the payload of the 291 message. A user of Gcs_message can freely add data to the header and to the 292 payload. 293 294 Each binding implementation might use these two fields at its own 295 discretion but that data should be removed from the header/payload 296 before its delivery to the client layer. 297 298 When the message is built, none of the data is passed unto it. One has to 299 use the append_* methods in order to append data. Calling encode() at the end 300 will provide a ready-to-send message. 301 302 On the receiver side, one shall use decode() in order to have the header and 303 the payload restored in the original message fields. 304 305 A typical use case of sending a message is: 306 307 @code{.cpp} 308 309 Gcs_control_interface *gcs_ctrl_interface_instance; 310 Gcs_communication_interface *gcs_comm_interface_instance; // obtained 311 // previously 312 313 Gcs_member_identifier *myself= 314 gcs_ctrl_interface_instance->get_local_information(); 315 316 Gcs_group_identifier destination("the_group"); 317 318 Gcs_message *msg= new Gcs_message(&myself, new Gcs_message_data(0, 3)); 319 320 uchar[] some_data= {(uchar)0x12, 321 (uchar)0x24, 322 (uchar)0x00}; 323 324 msg->get_message_data()->append_to_payload(&some_data, 325 strlen(some_data)); 326 327 gcs_comm_interface_instance->send_message(msg); 328 @endcode 329 330 A typical use case of receiving a message is: 331 332 @code{.cpp} 333 class my_Gcs_communication_event_listener : Gcs_communication_event_listener 334 { 335 my_Gcs_communication_event_listener(my_Message_delegator *delegator) 336 { 337 this->delegator= delegator; 338 } 339 340 void on_message_received(Gcs_message &message) 341 { 342 // Do something when message arrives... 343 delegator->process_gcs_message(message); 344 } 345 346 private: 347 my_Message_delegator *delegator; 348 } 349 @endcode 350 */ 351 class Gcs_message 352 { 353 public: 354 /** 355 Gcs_message 1st constructor. This is used to build full messages. 356 357 Note that the Gcs_message will acquire ownership of the data, i.e. 358 Gcs_message_data, and will be responsible for deleting it. 359 360 @param[in] origin The group member that sent the message 361 @param[in] destination The group in which this message belongs 362 @param[in] message_data External message data object. 363 */ 364 365 explicit Gcs_message(const Gcs_member_identifier &origin, 366 const Gcs_group_identifier &destination, 367 Gcs_message_data *message_data); 368 369 370 /** 371 Gcs_message 2nd constructor. This is used to send messages but with 372 an external Gcs_message_data object. 373 374 Note that the Gcs_message will acquire ownership of the data, i.e. 375 Gcs_message_data, and will be responsible for deleting it. 376 377 @param[in] origin The group member that sent the message 378 @param[in] message_data External message data object. 379 */ 380 381 explicit Gcs_message(const Gcs_member_identifier &origin, 382 Gcs_message_data *message_data); 383 384 385 virtual ~Gcs_message(); 386 387 388 /** 389 @return the origin of this message 390 */ 391 392 const Gcs_member_identifier &get_origin() const; 393 394 395 /** 396 @return the destination of this message. It might be NULL. 397 */ 398 399 const Gcs_group_identifier *get_destination() const; 400 401 402 /** 403 @return the message data to be filled. 404 */ 405 406 Gcs_message_data &get_message_data() const; 407 408 409 private: 410 void init(const Gcs_member_identifier *origin, 411 const Gcs_group_identifier *destination, 412 Gcs_message_data *message_data); 413 414 Gcs_member_identifier *m_origin; 415 Gcs_group_identifier *m_destination; 416 Gcs_message_data *m_data; 417 418 /* 419 Disabling the copy constructor and assignment operator. 420 */ 421 Gcs_message(Gcs_message const&); 422 Gcs_message& operator=(Gcs_message const&); 423 }; 424 425 #endif // GCS_GCS_MESSAGE_INCLUDED 426