Message.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. typedef 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* _msgbytes;
  32. /** Amount of bytes of storage space available in the message. */
  33. int32_t _capacity;
  34. // Amount of associated data
  35. int32_t _adLen;
  36. // Pointer to associated data
  37. uint8_t* _ad;
  38. /**
  39. * When sending/receiving a Message on a unix socket, a file descriptor to attach.
  40. * Caviat: In order to maintain backward compatibility with a Message which is
  41. * allocated using calloc, file descriptor 0 is referred to by -1
  42. */
  43. int _associatedFd;
  44. #ifdef PARANOIA
  45. /** This is used inside of Iface.h to support Iface_next() */
  46. struct Iface* currentIface;
  47. #endif
  48. /** The allocator which allocated space for this message. */
  49. struct Allocator* _alloc;
  50. } Message_t;
  51. static inline uint8_t* Message_bytes(struct Message* msg)
  52. {
  53. return msg->_msgbytes;
  54. }
  55. static inline struct Allocator* Message_getAlloc(struct Message* msg)
  56. {
  57. return msg->_alloc;
  58. }
  59. static inline int32_t Message_getLength(struct Message* msg)
  60. {
  61. return msg->_length;
  62. }
  63. static inline Er_DEFUN(void Message_truncate(struct Message* msg, int32_t newLen))
  64. {
  65. if (newLen > msg->_length) {
  66. Er_raise(msg->_alloc, "Message_truncate(%d) message length is %d", newLen, msg->_length);
  67. }
  68. msg->_length = newLen;
  69. Er_ret();
  70. }
  71. static inline int32_t Message_getPadding(struct Message* msg)
  72. {
  73. return msg->_padding;
  74. }
  75. static inline int32_t Message_getCapacity(struct Message* msg)
  76. {
  77. return msg->_capacity;
  78. }
  79. struct Message* Message_new(uint32_t messageLength,
  80. uint32_t amountOfPadding,
  81. struct Allocator* alloc);
  82. void Message_setAssociatedFd(struct Message* msg, int fd);
  83. int Message_getAssociatedFd(struct Message* msg);
  84. struct Message* Message_clone(struct Message* toClone, struct Allocator* alloc);
  85. static inline Er_DEFUN(uint8_t* Message_peakBytes(struct Message* msg, int32_t len))
  86. {
  87. if (len > msg->_length) {
  88. Er_raise(msg->_alloc, "peakBytes(%d) too big, message length is %d", len, msg->_length);
  89. }
  90. Er_ret(msg->_msgbytes);
  91. }
  92. /**
  93. * Pretend to shift the content forward by amount.
  94. * Really it shifts the bytes value backward.
  95. */
  96. static inline Er_DEFUN(void Message_eshift(struct Message* toShift, int32_t amount))
  97. {
  98. if (amount > 0 && toShift->_padding < amount) {
  99. Er_raise(toShift->_alloc, "buffer overflow adding %d to length %d",
  100. amount, toShift->_length);
  101. } else if (toShift->_length < (-amount)) {
  102. Er_raise(toShift->_alloc, "buffer underflow");
  103. }
  104. toShift->_length += amount;
  105. toShift->_capacity += amount;
  106. toShift->_msgbytes -= amount;
  107. toShift->_padding -= amount;
  108. Er_ret();
  109. }
  110. static inline Er_DEFUN(void Message_epushAd(struct Message* restrict msg,
  111. const void* restrict object,
  112. size_t size))
  113. {
  114. if (msg->_padding < (int)size) {
  115. Er_raise(msg->_alloc, "not enough padding to push ad");
  116. }
  117. if (object) {
  118. Bits_memcpy(msg->_ad, object, size);
  119. } else {
  120. Bits_memset(msg->_ad, 0x00, size);
  121. }
  122. msg->_adLen += size;
  123. msg->_padding -= size;
  124. msg->_ad = &msg->_ad[size];
  125. Er_ret();
  126. }
  127. static inline Er_DEFUN(void Message_epopAd(struct Message* restrict msg,
  128. void* restrict object,
  129. size_t size))
  130. {
  131. if (msg->_adLen < (int)size) {
  132. Er_raise(msg->_alloc, "underflow, cannot pop ad");
  133. }
  134. msg->_adLen -= size;
  135. msg->_padding += size;
  136. msg->_ad = &msg->_ad[-((int)size)];
  137. if (object) {
  138. Bits_memcpy(object, msg->_ad, size);
  139. }
  140. Er_ret();
  141. }
  142. static inline void Message_reset(struct Message* toShift)
  143. {
  144. Assert_true(toShift->_length <= toShift->_capacity);
  145. Er_assert(Message_epopAd(toShift, NULL, toShift->_adLen));
  146. toShift->_length = toShift->_capacity;
  147. Er_assert(Message_eshift(toShift, -toShift->_length));
  148. }
  149. static inline Er_DEFUN(void Message_epush(struct Message* restrict msg,
  150. const void* restrict object,
  151. size_t size))
  152. {
  153. Er(Message_eshift(msg, (int)size));
  154. if (object) {
  155. Bits_memcpy(msg->_msgbytes, object, size);
  156. } else {
  157. Bits_memset(msg->_msgbytes, 0x00, size);
  158. }
  159. Er_ret();
  160. }
  161. static inline Er_DEFUN(void Message_epop(struct Message* restrict msg,
  162. void* restrict object,
  163. size_t size))
  164. {
  165. Er(Message_eshift(msg, -(int)size));
  166. if (object) {
  167. Bits_memcpy(object, &msg->_msgbytes[-((int)size)], size);
  168. }
  169. Er_ret();
  170. }
  171. #define Message_pushH(size) \
  172. static inline Er_DEFUN(void Message_epush ## size ## h \
  173. (struct Message* msg, uint ## size ## _t dat)) \
  174. { \
  175. Er(Message_epush(msg, &dat, (size)/8)); \
  176. Er_ret(); \
  177. }
  178. #define Message_popH(size) \
  179. static inline Er_DEFUN(uint ## size ## _t Message_epop ## size ## h(struct Message* msg)) \
  180. { \
  181. uint ## size ## _t out; \
  182. Er(Message_epop(msg, &out, (size)/8)); \
  183. Er_ret(out); \
  184. }
  185. #define Message_popBE(size) \
  186. static inline Er_DEFUN(uint ## size ## _t Message_epop ## size ## be(struct Message* msg)) \
  187. { \
  188. uint ## size ## _t out = Er(Message_epop ## size ## h(msg)); \
  189. uint ## size ## _t out1 = Endian_bigEndianToHost ## size (out); \
  190. Er_ret(out1); \
  191. }
  192. #define Message_popLE(size) \
  193. static inline Er_DEFUN(uint ## size ## _t Message_epop ## size ## le(struct Message* msg)) \
  194. { \
  195. uint ## size ## _t out = Er(Message_epop ## size ## h(msg)); \
  196. uint ## size ## _t out1 = Endian_littleEndianToHost ## size (out); \
  197. Er_ret(out1); \
  198. }
  199. #define Message_pushPop(size) \
  200. Message_pushH(size) Message_popH(size) Message_popBE(size) Message_popLE(size)
  201. Message_pushH(8)
  202. Message_popH(8)
  203. #define Message_epush8 Message_epush8h
  204. #define Message_epop8 Message_epop8h
  205. Message_pushPop(16)
  206. Message_pushPop(32)
  207. Message_pushPop(64)
  208. #define Message_epush16le(msg, x) Message_epush16h(msg, Endian_hostToLittleEndian16(x))
  209. #define Message_epush32le(msg, x) Message_epush16h(msg, Endian_hostToLittleEndian32(x))
  210. #define Message_epush64le(msg, x) Message_epush16h(msg, Endian_hostToLittleEndian64(x))
  211. #define Message_epush16be(msg, x) Message_epush16h(msg, Endian_hostToBigEndian16(x))
  212. #define Message_epush32be(msg, x) Message_epush32h(msg, Endian_hostToBigEndian32(x))
  213. #define Message_epush64be(msg, x) Message_epush64h(msg, Endian_hostToBigEndian64(x))
  214. #endif