Message.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #ifndef Message_H
  16. #define Message_H
  17. #include "exception/Er.h"
  18. #include "memory/Allocator.h"
  19. #include "util/Bits.h"
  20. #include "util/Endian.h"
  21. #include "util/Linker.h"
  22. Linker_require("wire/Message.c");
  23. #include <stdint.h>
  24. struct Message
  25. {
  26. /** The length of the message. */
  27. int32_t length;
  28. /** The number of bytes of padding BEFORE where bytes begins. */
  29. int32_t padding;
  30. /** The content. */
  31. uint8_t* bytes;
  32. /** Amount of bytes of storage space available in the message. */
  33. int32_t capacity;
  34. /**
  35. * When sending/receiving a Message on a unix socket, a file descriptor to attach.
  36. * Caviat: In order to maintain backward compatibility with a Message which is
  37. * allocated using calloc, file descriptor 0 is referred to by -1
  38. */
  39. int associatedFd;
  40. #ifdef PARANOIA
  41. /** This is used inside of Iface.h to support Iface_next() */
  42. struct Iface* currentIface;
  43. #endif
  44. /** The allocator which allocated space for this message. */
  45. struct Allocator* alloc;
  46. };
  47. struct Message* Message_new(uint32_t messageLength,
  48. uint32_t amountOfPadding,
  49. struct Allocator* alloc);
  50. void Message_setAssociatedFd(struct Message* msg, int fd);
  51. int Message_getAssociatedFd(struct Message* msg);
  52. struct Message* Message_clone(struct Message* toClone, struct Allocator* alloc);
  53. void Message_copyOver(struct Message* output,
  54. struct Message* input,
  55. struct Allocator* allocator);
  56. /**
  57. * Pretend to shift the content forward by amount.
  58. * Really it shifts the bytes value backward.
  59. */
  60. static inline Er_DEFUN(void Message_eshift(struct Message* toShift, int32_t amount))
  61. {
  62. if (amount > 0 && toShift->padding < amount) {
  63. Er_raise(toShift->alloc, "buffer overflow adding %d to length %d",
  64. amount, toShift->length);
  65. } else if (toShift->length < (-amount)) {
  66. Er_raise(toShift->alloc, "buffer underflow");
  67. }
  68. toShift->length += amount;
  69. toShift->capacity += amount;
  70. toShift->bytes -= amount;
  71. toShift->padding -= amount;
  72. Er_ret();
  73. }
  74. static inline void Message_reset(struct Message* toShift)
  75. {
  76. Assert_true(toShift->length <= toShift->capacity);
  77. toShift->length = toShift->capacity;
  78. Er_assert(Message_eshift(toShift, -toShift->length));
  79. }
  80. static inline Er_DEFUN(void Message_epush(struct Message* restrict msg,
  81. const void* restrict object,
  82. size_t size))
  83. {
  84. Er(Message_eshift(msg, (int)size));
  85. if (object) {
  86. Bits_memcpy(msg->bytes, object, size);
  87. } else {
  88. Bits_memset(msg->bytes, 0x00, size);
  89. }
  90. Er_ret();
  91. }
  92. static inline Er_DEFUN(void Message_epop(struct Message* restrict msg,
  93. void* restrict object,
  94. size_t size))
  95. {
  96. Er(Message_eshift(msg, -(int)size));
  97. if (object) {
  98. Bits_memcpy(object, &msg->bytes[-((int)size)], size);
  99. }
  100. Er_ret();
  101. }
  102. #define Message_pushH(size) \
  103. static inline Er_DEFUN(void Message_epush ## size ## h \
  104. (struct Message* msg, uint ## size ## _t dat)) \
  105. { \
  106. Er(Message_epush(msg, &dat, (size)/8)); \
  107. Er_ret(); \
  108. }
  109. #define Message_popH(size) \
  110. static inline Er_DEFUN(uint ## size ## _t Message_epop ## size ## h(struct Message* msg)) \
  111. { \
  112. uint ## size ## _t out; \
  113. Er(Message_epop(msg, &out, (size)/8)); \
  114. Er_ret(out); \
  115. }
  116. #define Message_popBE(size) \
  117. static inline Er_DEFUN(uint ## size ## _t Message_epop ## size ## be(struct Message* msg)) \
  118. { \
  119. uint ## size ## _t out = Er(Message_epop ## size ## h(msg)); \
  120. uint ## size ## _t out1 = Endian_bigEndianToHost ## size (out); \
  121. Er_ret(out1); \
  122. }
  123. #define Message_popLE(size) \
  124. static inline Er_DEFUN(uint ## size ## _t Message_epop ## size ## le(struct Message* msg)) \
  125. { \
  126. uint ## size ## _t out = Er(Message_epop ## size ## h(msg)); \
  127. uint ## size ## _t out1 = Endian_littleEndianToHost ## size (out); \
  128. Er_ret(out1); \
  129. }
  130. #define Message_pushPop(size) \
  131. Message_pushH(size) Message_popH(size) Message_popBE(size) Message_popLE(size)
  132. Message_pushH(8)
  133. Message_popH(8)
  134. #define Message_epush8 Message_epush8h
  135. #define Message_epop8 Message_epop8h
  136. Message_pushPop(16)
  137. Message_pushPop(32)
  138. Message_pushPop(64)
  139. #define Message_epush16le(msg, x) Message_epush16h(msg, Endian_hostToLittleEndian16(x))
  140. #define Message_epush32le(msg, x) Message_epush16h(msg, Endian_hostToLittleEndian32(x))
  141. #define Message_epush64le(msg, x) Message_epush16h(msg, Endian_hostToLittleEndian64(x))
  142. #define Message_epush16be(msg, x) Message_epush16h(msg, Endian_hostToBigEndian16(x))
  143. #define Message_epush32be(msg, x) Message_epush32h(msg, Endian_hostToBigEndian32(x))
  144. #define Message_epush64be(msg, x) Message_epush64h(msg, Endian_hostToBigEndian64(x))
  145. #endif