Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Messages.hpp 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* Copyright 2016, Ableton AG, Berlin. All rights reserved.
  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 as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. * If you would like to incorporate Link into a proprietary software application,
  17. * please contact <link-devs@ableton.com>.
  18. */
  19. #pragma once
  20. #include <ableton/discovery/Payload.hpp>
  21. #include <array>
  22. namespace ableton
  23. {
  24. namespace discovery
  25. {
  26. namespace v1
  27. {
  28. // The maximum size of a message, in bytes
  29. const std::size_t kMaxMessageSize = 512;
  30. // Utility typedef for an array of bytes of maximum message size
  31. using MessageBuffer = std::array<uint8_t, v1::kMaxMessageSize>;
  32. using MessageType = uint8_t;
  33. using SessionGroupId = uint16_t;
  34. const MessageType kInvalid = 0;
  35. const MessageType kAlive = 1;
  36. const MessageType kResponse = 2;
  37. const MessageType kByeBye = 3;
  38. template <typename NodeId>
  39. struct MessageHeader
  40. {
  41. MessageType messageType;
  42. uint8_t ttl;
  43. SessionGroupId groupId;
  44. NodeId ident;
  45. friend std::uint32_t sizeInByteStream(const MessageHeader& header)
  46. {
  47. return discovery::sizeInByteStream(header.messageType)
  48. + discovery::sizeInByteStream(header.ttl)
  49. + discovery::sizeInByteStream(header.groupId)
  50. + discovery::sizeInByteStream(header.ident);
  51. }
  52. template <typename It>
  53. friend It toNetworkByteStream(const MessageHeader& header, It out)
  54. {
  55. return discovery::toNetworkByteStream(header.ident,
  56. discovery::toNetworkByteStream(header.groupId,
  57. discovery::toNetworkByteStream(header.ttl,
  58. discovery::toNetworkByteStream(header.messageType, std::move(out)))));
  59. }
  60. template <typename It>
  61. static std::pair<MessageHeader, It> fromNetworkByteStream(It begin, const It end)
  62. {
  63. using namespace std;
  64. MessageHeader header;
  65. tie(header.messageType, begin) =
  66. Deserialize<decltype(header.messageType)>::fromNetworkByteStream(begin, end);
  67. tie(header.ttl, begin) =
  68. Deserialize<decltype(header.ttl)>::fromNetworkByteStream(begin, end);
  69. tie(header.groupId, begin) =
  70. Deserialize<decltype(header.groupId)>::fromNetworkByteStream(begin, end);
  71. tie(header.ident, begin) =
  72. Deserialize<decltype(header.ident)>::fromNetworkByteStream(begin, end);
  73. return make_pair(move(header), move(begin));
  74. }
  75. };
  76. namespace detail
  77. {
  78. // Types that are only used in the sending/parsing of messages, not
  79. // publicly exposed.
  80. using ProtocolHeader = std::array<char, 8>;
  81. const ProtocolHeader kProtocolHeader = {{'_', 'a', 's', 'd', 'p', '_', 'v', 1}};
  82. // Must have at least kMaxMessageSize bytes available in the output stream
  83. template <typename NodeId, typename Payload, typename It>
  84. It encodeMessage(NodeId from,
  85. const uint8_t ttl,
  86. const MessageType messageType,
  87. const Payload& payload,
  88. It out)
  89. {
  90. using namespace std;
  91. const MessageHeader<NodeId> header = {messageType, ttl, 0, std::move(from)};
  92. const auto messageSize =
  93. kProtocolHeader.size() + sizeInByteStream(header) + sizeInByteStream(payload);
  94. if (messageSize < kMaxMessageSize)
  95. {
  96. return toNetworkByteStream(
  97. payload, toNetworkByteStream(
  98. header, copy(begin(kProtocolHeader), end(kProtocolHeader), move(out))));
  99. }
  100. else
  101. {
  102. throw range_error("Exceeded maximum message size");
  103. }
  104. }
  105. } // namespace detail
  106. template <typename NodeId, typename Payload, typename It>
  107. It aliveMessage(NodeId from, const uint8_t ttl, const Payload& payload, It out)
  108. {
  109. return detail::encodeMessage(std::move(from), ttl, kAlive, payload, std::move(out));
  110. }
  111. template <typename NodeId, typename Payload, typename It>
  112. It responseMessage(NodeId from, const uint8_t ttl, const Payload& payload, It out)
  113. {
  114. return detail::encodeMessage(std::move(from), ttl, kResponse, payload, std::move(out));
  115. }
  116. template <typename NodeId, typename It>
  117. It byeByeMessage(NodeId from, It out)
  118. {
  119. return detail::encodeMessage(
  120. std::move(from), 0, kByeBye, makePayload(), std::move(out));
  121. }
  122. template <typename NodeId, typename It>
  123. std::pair<MessageHeader<NodeId>, It> parseMessageHeader(It bytesBegin, const It bytesEnd)
  124. {
  125. using namespace std;
  126. using ItDiff = typename iterator_traits<It>::difference_type;
  127. MessageHeader<NodeId> header = {};
  128. const auto protocolHeaderSize = discovery::sizeInByteStream(detail::kProtocolHeader);
  129. const auto minMessageSize =
  130. static_cast<ItDiff>(protocolHeaderSize + sizeInByteStream(header));
  131. // If there are enough bytes in the stream to make a header and if
  132. // the first bytes in the stream are the protocol header, then
  133. // proceed to parse the stream.
  134. if (distance(bytesBegin, bytesEnd) >= minMessageSize
  135. && equal(begin(detail::kProtocolHeader), end(detail::kProtocolHeader), bytesBegin))
  136. {
  137. tie(header, bytesBegin) = MessageHeader<NodeId>::fromNetworkByteStream(
  138. bytesBegin + protocolHeaderSize, bytesEnd);
  139. }
  140. return make_pair(move(header), move(bytesBegin));
  141. }
  142. } // namespace v1
  143. } // namespace discovery
  144. } // namespace ableton