mediahandlerelement.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * Copyright (c) 2020 Filip Klembara (in2core)
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #if RTC_ENABLE_MEDIA
  18. #include "mediahandlerelement.hpp"
  19. namespace rtc {
  20. ChainedMessagesProduct make_chained_messages_product() {
  21. return std::make_shared<std::vector<binary_ptr>>();
  22. }
  23. ChainedMessagesProduct make_chained_messages_product(message_ptr msg) {
  24. std::vector<binary_ptr> msgs = {msg};
  25. return std::make_shared<std::vector<binary_ptr>>(msgs);
  26. }
  27. ChainedOutgoingProduct::ChainedOutgoingProduct(ChainedMessagesProduct messages, message_ptr control)
  28. : messages(messages), control(control) { }
  29. ChainedIncomingProduct::ChainedIncomingProduct(ChainedMessagesProduct incoming, ChainedMessagesProduct outgoing)
  30. : incoming(incoming), outgoing(outgoing) { }
  31. ChainedIncomingControlProduct::ChainedIncomingControlProduct(message_ptr incoming, std::optional<ChainedOutgoingProduct> outgoing)
  32. : incoming(incoming), outgoing(outgoing) { }
  33. MediaHandlerElement::MediaHandlerElement() { }
  34. void MediaHandlerElement::removeFromChain() {
  35. if (upstream) {
  36. upstream->downstream = downstream;
  37. }
  38. if (downstream) {
  39. downstream->upstream = upstream;
  40. }
  41. upstream = nullptr;
  42. downstream = nullptr;
  43. }
  44. void MediaHandlerElement::recursiveRemoveChain() {
  45. if (downstream) {
  46. // `recursiveRemoveChain` removes last strong reference to downstream element
  47. // we need to keep strong reference to prevent deallocation of downstream element
  48. // during `recursiveRemoveChain`
  49. auto strongDownstreamPtr = downstream;
  50. downstream->recursiveRemoveChain();
  51. }
  52. removeFromChain();
  53. }
  54. std::optional<ChainedOutgoingProduct> MediaHandlerElement::processOutgoingResponse(ChainedOutgoingProduct messages) {
  55. if (messages.messages) {
  56. if (upstream) {
  57. auto msgs = upstream->formOutgoingBinaryMessage(ChainedOutgoingProduct(messages.messages, messages.control));
  58. if (msgs.has_value()) {
  59. return msgs.value();
  60. } else {
  61. LOG_ERROR << "Generating outgoing message failed";
  62. return nullopt;
  63. }
  64. } else {
  65. return messages;
  66. }
  67. } else if (messages.control) {
  68. if (upstream) {
  69. auto control = upstream->formOutgoingControlMessage(messages.control);
  70. if (control) {
  71. return ChainedOutgoingProduct(nullptr, control);
  72. } else {
  73. LOG_ERROR << "Generating outgoing control message failed";
  74. return nullopt;
  75. }
  76. } else {
  77. return messages;
  78. }
  79. } else {
  80. return ChainedOutgoingProduct();
  81. }
  82. }
  83. void MediaHandlerElement::prepareAndSendResponse(std::optional<ChainedOutgoingProduct> outgoing, std::function<bool (ChainedOutgoingProduct)> send) {
  84. if (outgoing.has_value()) {
  85. auto message = outgoing.value();
  86. auto response = processOutgoingResponse(message);
  87. if (response.has_value()) {
  88. if(!send(response.value())) {
  89. LOG_DEBUG << "Send failed";
  90. }
  91. } else {
  92. LOG_DEBUG << "No response to send";
  93. }
  94. }
  95. }
  96. message_ptr MediaHandlerElement::formIncomingControlMessage(message_ptr message, std::function<bool (ChainedOutgoingProduct)> send) {
  97. assert(message);
  98. auto product = processIncomingControlMessage(message);
  99. prepareAndSendResponse(product.outgoing, send);
  100. if (product.incoming) {
  101. if (downstream) {
  102. return downstream->formIncomingControlMessage(product.incoming, send);
  103. } else {
  104. return product.incoming;
  105. }
  106. } else {
  107. return nullptr;
  108. }
  109. }
  110. ChainedMessagesProduct MediaHandlerElement::formIncomingBinaryMessage(ChainedMessagesProduct messages, std::function<bool (ChainedOutgoingProduct)> send) {
  111. assert(messages && !messages->empty());
  112. auto product = processIncomingBinaryMessage(messages);
  113. prepareAndSendResponse(product.outgoing, send);
  114. if (product.incoming) {
  115. if (downstream) {
  116. return downstream->formIncomingBinaryMessage(product.incoming, send);
  117. } else {
  118. return product.incoming;
  119. }
  120. } else {
  121. return nullptr;
  122. }
  123. }
  124. message_ptr MediaHandlerElement::formOutgoingControlMessage(message_ptr message) {
  125. assert(message);
  126. auto newMessage = processOutgoingControlMessage(message);
  127. assert(newMessage);
  128. if(!newMessage) {
  129. LOG_ERROR << "Failed to generate outgoing message";
  130. return nullptr;
  131. }
  132. if (upstream) {
  133. return upstream->formOutgoingControlMessage(newMessage);
  134. } else {
  135. return newMessage;
  136. }
  137. }
  138. std::optional<ChainedOutgoingProduct> MediaHandlerElement::formOutgoingBinaryMessage(ChainedOutgoingProduct product) {
  139. assert(product.messages && !product.messages->empty());
  140. auto newProduct = processOutgoingBinaryMessage(product.messages, product.control);
  141. assert(!product.control || newProduct.control);
  142. assert(newProduct.messages && !newProduct.messages->empty());
  143. if (product.control && !newProduct.control) {
  144. LOG_ERROR << "Outgoing message must not remove control message";
  145. return nullopt;
  146. }
  147. if (!newProduct.messages || newProduct.messages->empty()) {
  148. LOG_ERROR << "Failed to generate message";
  149. return nullopt;
  150. }
  151. if (upstream) {
  152. return upstream->formOutgoingBinaryMessage(newProduct);
  153. } else {
  154. return newProduct;
  155. }
  156. }
  157. ChainedIncomingControlProduct MediaHandlerElement::processIncomingControlMessage(message_ptr messages) {
  158. return {messages};
  159. }
  160. message_ptr MediaHandlerElement::processOutgoingControlMessage(message_ptr messages) {
  161. return messages;
  162. }
  163. ChainedIncomingProduct MediaHandlerElement::processIncomingBinaryMessage(ChainedMessagesProduct messages) {
  164. return {messages};
  165. }
  166. ChainedOutgoingProduct MediaHandlerElement::processOutgoingBinaryMessage(ChainedMessagesProduct messages, message_ptr control) {
  167. return {messages, control};
  168. }
  169. std::shared_ptr<MediaHandlerElement> MediaHandlerElement::chainWith(std::shared_ptr<MediaHandlerElement> upstream) {
  170. assert(this->upstream == nullptr);
  171. assert(upstream->downstream == nullptr);
  172. this->upstream = upstream;
  173. upstream->downstream = shared_from_this();
  174. return upstream;
  175. }
  176. } // namespace rtc
  177. #endif /* RTC_ENABLE_MEDIA */