#if RTC_ENABLE_MEDIA
#include "mediahandlerelement.hpp"
namespace rtc {
ChainedMessagesProduct make_chained_messages_product() {
return std::make_shared<std::vector<binary_ptr>>();
}
ChainedMessagesProduct make_chained_messages_product(message_ptr msg) {
std::vector<binary_ptr> msgs = {msg};
return std::make_shared<std::vector<binary_ptr>>(msgs);
}
ChainedOutgoingProduct::ChainedOutgoingProduct(ChainedMessagesProduct messages, message_ptr control)
: messages(messages), control(control) { }
ChainedIncomingProduct::ChainedIncomingProduct(ChainedMessagesProduct incoming, ChainedMessagesProduct outgoing)
: incoming(incoming), outgoing(outgoing) { }
ChainedIncomingControlProduct::ChainedIncomingControlProduct(message_ptr incoming, std::optional<ChainedOutgoingProduct> outgoing)
: incoming(incoming), outgoing(outgoing) { }
MediaHandlerElement::MediaHandlerElement() { }
void MediaHandlerElement::removeFromChain() {
if (upstream) {
upstream->downstream = downstream;
}
if (downstream) {
downstream->upstream = upstream;
}
upstream = nullptr;
downstream = nullptr;
}
void MediaHandlerElement::recursiveRemoveChain() {
if (downstream) {
auto strongDownstreamPtr = downstream;
downstream->recursiveRemoveChain();
}
removeFromChain();
}
std::optional<ChainedOutgoingProduct> MediaHandlerElement::processOutgoingResponse(ChainedOutgoingProduct messages) {
if (messages.messages) {
if (upstream) {
auto msgs = upstream->formOutgoingBinaryMessage(ChainedOutgoingProduct(messages.messages, messages.control));
if (msgs.has_value()) {
return msgs.value();
} else {
LOG_ERROR << "Generating outgoing message failed";
return nullopt;
}
} else {
return messages;
}
} else if (messages.control) {
if (upstream) {
auto control = upstream->formOutgoingControlMessage(messages.control);
if (control) {
return ChainedOutgoingProduct(nullptr, control);
} else {
LOG_ERROR << "Generating outgoing control message failed";
return nullopt;
}
} else {
return messages;
}
} else {
return ChainedOutgoingProduct();
}
}
void MediaHandlerElement::prepareAndSendResponse(std::optional<ChainedOutgoingProduct> outgoing, std::function<bool (ChainedOutgoingProduct)> send) {
if (outgoing.has_value()) {
auto message = outgoing.value();
auto response = processOutgoingResponse(message);
if (response.has_value()) {
if(!send(response.value())) {
LOG_DEBUG << "Send failed";
}
} else {
LOG_DEBUG << "No response to send";
}
}
}
message_ptr MediaHandlerElement::formIncomingControlMessage(message_ptr message, std::function<bool (ChainedOutgoingProduct)> send) {
assert(message);
auto product = processIncomingControlMessage(message);
prepareAndSendResponse(product.outgoing, send);
if (product.incoming) {
if (downstream) {
return downstream->formIncomingControlMessage(product.incoming, send);
} else {
return product.incoming;
}
} else {
return nullptr;
}
}
ChainedMessagesProduct MediaHandlerElement::formIncomingBinaryMessage(ChainedMessagesProduct messages, std::function<bool (ChainedOutgoingProduct)> send) {
assert(messages && !messages->empty());
auto product = processIncomingBinaryMessage(messages);
prepareAndSendResponse(product.outgoing, send);
if (product.incoming) {
if (downstream) {
return downstream->formIncomingBinaryMessage(product.incoming, send);
} else {
return product.incoming;
}
} else {
return nullptr;
}
}
message_ptr MediaHandlerElement::formOutgoingControlMessage(message_ptr message) {
assert(message);
auto newMessage = processOutgoingControlMessage(message);
assert(newMessage);
if(!newMessage) {
LOG_ERROR << "Failed to generate outgoing message";
return nullptr;
}
if (upstream) {
return upstream->formOutgoingControlMessage(newMessage);
} else {
return newMessage;
}
}
std::optional<ChainedOutgoingProduct> MediaHandlerElement::formOutgoingBinaryMessage(ChainedOutgoingProduct product) {
assert(product.messages && !product.messages->empty());
auto newProduct = processOutgoingBinaryMessage(product.messages, product.control);
assert(!product.control || newProduct.control);
assert(newProduct.messages && !newProduct.messages->empty());
if (product.control && !newProduct.control) {
LOG_ERROR << "Outgoing message must not remove control message";
return nullopt;
}
if (!newProduct.messages || newProduct.messages->empty()) {
LOG_ERROR << "Failed to generate message";
return nullopt;
}
if (upstream) {
return upstream->formOutgoingBinaryMessage(newProduct);
} else {
return newProduct;
}
}
ChainedIncomingControlProduct MediaHandlerElement::processIncomingControlMessage(message_ptr messages) {
return {messages};
}
message_ptr MediaHandlerElement::processOutgoingControlMessage(message_ptr messages) {
return messages;
}
ChainedIncomingProduct MediaHandlerElement::processIncomingBinaryMessage(ChainedMessagesProduct messages) {
return {messages};
}
ChainedOutgoingProduct MediaHandlerElement::processOutgoingBinaryMessage(ChainedMessagesProduct messages, message_ptr control) {
return {messages, control};
}
std::shared_ptr<MediaHandlerElement> MediaHandlerElement::chainWith(std::shared_ptr<MediaHandlerElement> upstream) {
assert(this->upstream == nullptr);
assert(upstream->downstream == nullptr);
this->upstream = upstream;
upstream->downstream = shared_from_this();
return upstream;
}
}
#endif