diff --git a/src/internal_modules/roc_audio/packetizer.cpp b/src/internal_modules/roc_audio/packetizer.cpp index 656f593993..50f2d56d30 100644 --- a/src/internal_modules/roc_audio/packetizer.cpp +++ b/src/internal_modules/roc_audio/packetizer.cpp @@ -10,6 +10,7 @@ #include "roc_core/fast_random.h" #include "roc_core/log.h" #include "roc_core/panic.h" +#include "roc_status/code_to_str.h" namespace roc { namespace audio { @@ -125,7 +126,13 @@ void Packetizer::end_packet_() { pad_packet_(); } - writer_.write(packet_); + const status::StatusCode code = writer_.write(packet_); + if (code != status::StatusOK) { + // TODO: handle returned status code (gh-183). + roc_panic_if_msg(code != status::StatusNoData, + "packetizer: failed to write packet: status=%s", + status::code_to_str(code)); + } seqnum_++; stream_ts_ += (packet::stream_timestamp_t)packet_pos_; diff --git a/src/internal_modules/roc_fec/reader.cpp b/src/internal_modules/roc_fec/reader.cpp index 954b007408..60990ce393 100644 --- a/src/internal_modules/roc_fec/reader.cpp +++ b/src/internal_modules/roc_fec/reader.cpp @@ -288,7 +288,7 @@ status::StatusCode Reader::fetch_packets_(packet::IReader& reader, for (;;) { packet::PacketPtr pp; - const status::StatusCode code = reader.read(pp); + status::StatusCode code = reader.read(pp); if (code != status::StatusOK) { if (code == status::StatusNoData) { break; @@ -300,7 +300,13 @@ status::StatusCode Reader::fetch_packets_(packet::IReader& reader, break; } - writer.write(pp); + code = writer.write(pp); + if (code != status::StatusOK) { + // TODO: properly handle returned status (gh-183) + roc_panic_if_msg(code != status::StatusNoData, + "fec reader: failed to write fetched packets: status=%s", + status::code_to_str(code)); + } } return status::StatusOK; diff --git a/src/internal_modules/roc_fec/writer.cpp b/src/internal_modules/roc_fec/writer.cpp index 83ad059ba1..745d0be0f1 100644 --- a/src/internal_modules/roc_fec/writer.cpp +++ b/src/internal_modules/roc_fec/writer.cpp @@ -11,6 +11,7 @@ #include "roc_core/log.h" #include "roc_core/panic.h" #include "roc_packet/fec_scheme_to_str.h" +#include "roc_status/code_to_str.h" namespace roc { namespace fec { @@ -92,12 +93,13 @@ bool Writer::resize(size_t sblen, size_t rblen) { return true; } -void Writer::write(const packet::PacketPtr& pp) { +status::StatusCode Writer::write(const packet::PacketPtr& pp) { roc_panic_if_not(is_valid()); roc_panic_if_not(pp); if (!alive_) { - return; + // TODO: return StatusDead (gh-183) + return status::StatusNoData; } validate_fec_packet_(pp); @@ -108,15 +110,23 @@ void Writer::write(const packet::PacketPtr& pp) { if (cur_packet_ == 0) { if (!begin_block_(pp)) { - return; + // TODO: return StatusDead (gh-183) + return status::StatusNoData; } } if (!validate_source_packet_(pp)) { - return; + // TODO: return StatusDead (gh-183) + return status::StatusNoData; } - write_source_packet_(pp); + const status::StatusCode code = write_source_packet_(pp); + if (code != status::StatusOK) { + // TODO: handle returned status code (gh-183). + roc_panic_if_msg(code != status::StatusNoData, + "fec writer: failed to write source packet: status=%s", + status::code_to_str(code)); + } cur_packet_++; @@ -124,6 +134,8 @@ void Writer::write(const packet::PacketPtr& pp) { end_block_(); next_block_(); } + + return status::StatusOK; } bool Writer::begin_block_(const packet::PacketPtr& pp) { @@ -185,7 +197,7 @@ bool Writer::apply_sizes_(size_t sblen, size_t rblen, size_t payload_size) { return true; } -void Writer::write_source_packet_(const packet::PacketPtr& pp) { +status::StatusCode Writer::write_source_packet_(const packet::PacketPtr& pp) { encoder_.set(cur_packet_, pp->fec()->payload); pp->add_flags(packet::Packet::FlagComposed); @@ -195,7 +207,7 @@ void Writer::write_source_packet_(const packet::PacketPtr& pp) { roc_panic("fec writer: can't compose source packet"); } - writer_.write(pp); + return writer_.write(pp); } void Writer::make_repair_packets_() { @@ -272,10 +284,19 @@ void Writer::compose_repair_packets_() { void Writer::write_repair_packets_() { for (size_t i = 0; i < cur_rblen_; i++) { packet::PacketPtr rp = repair_block_[i]; - if (rp) { - writer_.write(repair_block_[i]); - repair_block_[i] = NULL; + if (!rp) { + continue; } + + const status::StatusCode code = writer_.write(repair_block_[i]); + if (code != status::StatusOK) { + // TODO: handle returned status code (gh-183). + roc_panic_if_msg(code != status::StatusNoData, + "fec writer: failed to write repair packet: status=%s", + status::code_to_str(code)); + } + + repair_block_[i] = NULL; } } diff --git a/src/internal_modules/roc_fec/writer.h b/src/internal_modules/roc_fec/writer.h index 788d7f4b92..cc06bf9965 100644 --- a/src/internal_modules/roc_fec/writer.h +++ b/src/internal_modules/roc_fec/writer.h @@ -77,7 +77,7 @@ class Writer : public packet::IWriter, public core::NonCopyable<> { //! @remarks //! - writes the given source packet to the output writer //! - generates repair packets and also writes them to the output writer - virtual void write(const packet::PacketPtr&); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr&); private: bool begin_block_(const packet::PacketPtr& pp); @@ -86,7 +86,7 @@ class Writer : public packet::IWriter, public core::NonCopyable<> { bool apply_sizes_(size_t sblen, size_t rblen, size_t payload_size); - void write_source_packet_(const packet::PacketPtr&); + status::StatusCode write_source_packet_(const packet::PacketPtr&); void make_repair_packets_(); packet::PacketPtr make_repair_packet_(packet::seqnum_t n); void encode_repair_packets_(); diff --git a/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_receiver_port.cpp b/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_receiver_port.cpp index 84df2f7407..54290b5622 100644 --- a/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_receiver_port.cpp +++ b/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_receiver_port.cpp @@ -12,6 +12,7 @@ #include "roc_core/panic.h" #include "roc_core/shared_ptr.h" #include "roc_core/string_builder.h" +#include "roc_status/code_to_str.h" namespace roc { namespace netio { @@ -289,7 +290,13 @@ void UdpReceiverPort::recv_cb_(uv_udp_t* handle, pp->set_data(core::Slice(*bp, 0, (size_t)nread)); - self.writer_.write(pp); + const status::StatusCode code = self.writer_.write(pp); + if (code != status::StatusOK) { + // TODO: handle status code (gh-183) + roc_panic_if_msg(code != status::StatusNoData, + "udp receiver: failed to write packet: status=%s", + status::code_to_str(code)); + } } bool UdpReceiverPort::join_multicast_group_() { diff --git a/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_sender_port.cpp b/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_sender_port.cpp index 3de07bb647..c16b6fe037 100644 --- a/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_sender_port.cpp +++ b/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_sender_port.cpp @@ -154,7 +154,7 @@ AsyncOperationStatus UdpSenderPort::async_close(ICloseHandler& handler, return AsyncOp_Started; } -void UdpSenderPort::write(const packet::PacketPtr& pp) { +status::StatusCode UdpSenderPort::write(const packet::PacketPtr& pp) { if (!pp) { roc_panic("udp sender: %s: unexpected null packet", descriptor()); } @@ -174,6 +174,8 @@ void UdpSenderPort::write(const packet::PacketPtr& pp) { write_(pp); report_stats_(); + + return status::StatusOK; } void UdpSenderPort::write_(const packet::PacketPtr& pp) { diff --git a/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_sender_port.h b/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_sender_port.h index 03d202118c..f232516e7e 100644 --- a/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_sender_port.h +++ b/src/internal_modules/roc_netio/target_libuv/roc_netio/udp_sender_port.h @@ -77,7 +77,7 @@ class UdpSenderPort : public BasicPort, public packet::IWriter { //! Write packet. //! @remarks //! May be called from any thread. - virtual void write(const packet::PacketPtr&); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr&); protected: //! Format descriptor. diff --git a/src/internal_modules/roc_node/receiver_decoder.cpp b/src/internal_modules/roc_node/receiver_decoder.cpp index dd8f6d43b5..8977fd5735 100644 --- a/src/internal_modules/roc_node/receiver_decoder.cpp +++ b/src/internal_modules/roc_node/receiver_decoder.cpp @@ -10,6 +10,7 @@ #include "roc_address/interface.h" #include "roc_core/log.h" #include "roc_core/panic.h" +#include "roc_status/code_to_str.h" namespace roc { namespace node { @@ -134,7 +135,8 @@ bool ReceiverDecoder::get_metrics(pipeline::ReceiverSlotMetrics& slot_metrics, return true; } -bool ReceiverDecoder::write(address::Interface iface, const packet::PacketPtr& packet) { +status::StatusCode ReceiverDecoder::write(address::Interface iface, + const packet::PacketPtr& packet) { roc_panic_if_not(is_valid()); roc_panic_if(iface < 0); @@ -146,11 +148,11 @@ bool ReceiverDecoder::write(address::Interface iface, const packet::PacketPtr& p "receiver decoder node:" " can't write to %s interface: interface not activated", address::interface_to_str(iface)); - return false; + // TODO: return StatusNotFound (gh-183) + return status::StatusNoData; } - writer->write(packet); - return true; + return writer->write(packet); } sndio::ISource& ReceiverDecoder::source() { diff --git a/src/internal_modules/roc_node/receiver_decoder.h b/src/internal_modules/roc_node/receiver_decoder.h index f3499949ec..7fe657ccd5 100644 --- a/src/internal_modules/roc_node/receiver_decoder.h +++ b/src/internal_modules/roc_node/receiver_decoder.h @@ -14,11 +14,13 @@ #include "roc_address/interface.h" #include "roc_address/protocol.h" +#include "roc_core/attributes.h" #include "roc_core/mutex.h" #include "roc_node/context.h" #include "roc_node/node.h" #include "roc_pipeline/ipipeline_task_scheduler.h" #include "roc_pipeline/receiver_loop.h" +#include "roc_status/status_code.h" namespace roc { namespace node { @@ -54,7 +56,8 @@ class ReceiverDecoder : public Node, private pipeline::IPipelineTaskScheduler { void* sess_metrics_arg); //! Write packet for decoding. - bool write(address::Interface iface, const packet::PacketPtr& packet); + ROC_ATTR_NODISCARD status::StatusCode write(address::Interface iface, + const packet::PacketPtr& packet); //! Source for reading decoded frames. sndio::ISource& source(); diff --git a/src/internal_modules/roc_packet/concurrent_queue.cpp b/src/internal_modules/roc_packet/concurrent_queue.cpp index 438fc47633..f083fb944b 100644 --- a/src/internal_modules/roc_packet/concurrent_queue.cpp +++ b/src/internal_modules/roc_packet/concurrent_queue.cpp @@ -34,7 +34,7 @@ status::StatusCode ConcurrentQueue::read(PacketPtr& ptr) { return status::StatusOK; } -void ConcurrentQueue::write(const PacketPtr& packet) { +status::StatusCode ConcurrentQueue::write(const PacketPtr& packet) { if (!packet) { roc_panic("concurrent queue: packet is null"); } @@ -44,6 +44,8 @@ void ConcurrentQueue::write(const PacketPtr& packet) { if (write_sem_) { write_sem_->post(); } + + return status::StatusOK; } } // namespace packet diff --git a/src/internal_modules/roc_packet/concurrent_queue.h b/src/internal_modules/roc_packet/concurrent_queue.h index 5a144dca6c..b3f2a8542f 100644 --- a/src/internal_modules/roc_packet/concurrent_queue.h +++ b/src/internal_modules/roc_packet/concurrent_queue.h @@ -45,7 +45,7 @@ class ConcurrentQueue : public IReader, public IWriter, public core::NonCopyable //! Add packet to the queue. //! Wait-free operation. - virtual void write(const PacketPtr& packet); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const PacketPtr& packet); private: core::Optional write_sem_; diff --git a/src/internal_modules/roc_packet/delayed_reader.cpp b/src/internal_modules/roc_packet/delayed_reader.cpp index 2425020b8c..1d42de598f 100644 --- a/src/internal_modules/roc_packet/delayed_reader.cpp +++ b/src/internal_modules/roc_packet/delayed_reader.cpp @@ -9,6 +9,7 @@ #include "roc_packet/delayed_reader.h" #include "roc_core/log.h" #include "roc_core/panic.h" +#include "roc_status/code_to_str.h" #include "roc_status/status_code.h" namespace roc { @@ -44,7 +45,7 @@ status::StatusCode DelayedReader::read(PacketPtr& ptr) { status::StatusCode DelayedReader::fetch_packets_() { PacketPtr pp; for (;;) { - const status::StatusCode code = reader_.read(pp); + status::StatusCode code = reader_.read(pp); if (code != status::StatusOK) { if (code == status::StatusNoData) { break; @@ -52,7 +53,13 @@ status::StatusCode DelayedReader::fetch_packets_() { return code; } - queue_.write(pp); + code = queue_.write(pp); + if (code != status::StatusOK) { + // TODO: properly handle returned status (gh-183) + roc_panic_if_msg(code != status::StatusNoData, + "delayed reader: failed to write fetched packets: status=%s", + status::code_to_str(code)); + } } const stream_timestamp_t qs = queue_size_(); diff --git a/src/internal_modules/roc_packet/interleaver.cpp b/src/internal_modules/roc_packet/interleaver.cpp index b48a03ca46..7b7ca89a15 100644 --- a/src/internal_modules/roc_packet/interleaver.cpp +++ b/src/internal_modules/roc_packet/interleaver.cpp @@ -9,6 +9,7 @@ #include "roc_packet/interleaver.h" #include "roc_core/fast_random.h" #include "roc_core/log.h" +#include "roc_status/code_to_str.h" namespace roc { namespace packet { @@ -46,27 +47,39 @@ bool Interleaver::is_valid() const { return valid_; } -void Interleaver::write(const PacketPtr& p) { +status::StatusCode Interleaver::write(const PacketPtr& p) { roc_panic_if_not(is_valid()); packets_[next_2_put_] = p; next_2_put_ = (next_2_put_ + 1) % block_size_; while (packets_[send_seq_[next_2_send_]]) { - writer_.write(packets_[send_seq_[next_2_send_]]); + const status::StatusCode code = writer_.write(packets_[send_seq_[next_2_send_]]); + if (code != status::StatusOK) { + return code; + } + packets_[send_seq_[next_2_send_]] = NULL; next_2_send_ = (next_2_send_ + 1) % block_size_; } + + return status::StatusOK; } void Interleaver::flush() { roc_panic_if_not(is_valid()); for (size_t i = 0; i < block_size_; ++i) { - if (packets_[i]) { - writer_.write(packets_[i]); - packets_[i] = NULL; + if (!packets_[i]) { + continue; } + + const status::StatusCode code = writer_.write(packets_[i]); + roc_panic_if_msg(code != status::StatusOK, + "interleaver: failed to write packet: status=%s", + status::code_to_str(code)); + + packets_[i] = NULL; } next_2_put_ = next_2_send_ = 0; diff --git a/src/internal_modules/roc_packet/interleaver.h b/src/internal_modules/roc_packet/interleaver.h index fbcead0804..df06c936c2 100644 --- a/src/internal_modules/roc_packet/interleaver.h +++ b/src/internal_modules/roc_packet/interleaver.h @@ -37,7 +37,7 @@ class Interleaver : public IWriter, public core::NonCopyable<> { //! @remarks //! Packets are written to internal buffer. Buffered packets are //! then reordered and sent to output writer. - virtual void write(const PacketPtr& packet); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const PacketPtr& packet); //! Send all buffered packets to output writer. void flush(); diff --git a/src/internal_modules/roc_packet/iwriter.h b/src/internal_modules/roc_packet/iwriter.h index e8ed2f03f4..0e359c5393 100644 --- a/src/internal_modules/roc_packet/iwriter.h +++ b/src/internal_modules/roc_packet/iwriter.h @@ -12,7 +12,9 @@ #ifndef ROC_PACKET_IWRITER_H_ #define ROC_PACKET_IWRITER_H_ +#include "roc_core/attributes.h" #include "roc_packet/packet.h" +#include "roc_status/status_code.h" namespace roc { namespace packet { @@ -23,7 +25,13 @@ class IWriter { virtual ~IWriter(); //! Write packet. - virtual void write(const PacketPtr&) = 0; + //! + //! @returns + //! - If a returned code is not status::StatusOK, a packet is never written; + //! - If a packet is written, a returned code is always status::StatusOK. + //! + //! @see status::StatusCode. + virtual ROC_ATTR_NODISCARD status::StatusCode write(const PacketPtr&) = 0; }; } // namespace packet diff --git a/src/internal_modules/roc_packet/queue.cpp b/src/internal_modules/roc_packet/queue.cpp index 19af998917..f2728762a9 100644 --- a/src/internal_modules/roc_packet/queue.cpp +++ b/src/internal_modules/roc_packet/queue.cpp @@ -21,11 +21,12 @@ status::StatusCode Queue::read(PacketPtr& packet) { return status::StatusOK; } -void Queue::write(const PacketPtr& packet) { +status::StatusCode Queue::write(const PacketPtr& packet) { if (!packet) { roc_panic("queue: null packet"); } list_.push_back(*packet); + return status::StatusOK; } size_t Queue::size() const { diff --git a/src/internal_modules/roc_packet/queue.h b/src/internal_modules/roc_packet/queue.h index aabd0b19f0..83c2511077 100644 --- a/src/internal_modules/roc_packet/queue.h +++ b/src/internal_modules/roc_packet/queue.h @@ -30,7 +30,7 @@ class Queue : public IReader, public IWriter, public core::NonCopyable<> { //! Add packet to the queue. //! @remarks //! Adds packet to the end of the queue. - virtual void write(const PacketPtr& packet); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const PacketPtr& packet); //! Get number of packets in queue. size_t size() const; diff --git a/src/internal_modules/roc_packet/router.cpp b/src/internal_modules/roc_packet/router.cpp index 78c625c28d..b86ba5a30d 100644 --- a/src/internal_modules/roc_packet/router.cpp +++ b/src/internal_modules/roc_packet/router.cpp @@ -9,6 +9,7 @@ #include "roc_packet/router.h" #include "roc_core/log.h" #include "roc_core/panic.h" +#include "roc_status/status_code.h" namespace roc { namespace packet { @@ -33,7 +34,7 @@ bool Router::add_route(IWriter& writer, unsigned flags) { return true; } -void Router::write(const PacketPtr& packet) { +status::StatusCode Router::write(const PacketPtr& packet) { if (!packet) { roc_panic("router: unexpected null packet"); } @@ -63,11 +64,12 @@ void Router::write(const PacketPtr& packet) { (unsigned long)r.source, (unsigned int)r.flags); } - r.writer->write(packet); - return; + return r.writer->write(packet); } roc_log(LogDebug, "router: can't route packet, dropping"); + // TODO: return StatusNotFound (gh-183) + return status::StatusNoData; } } // namespace packet diff --git a/src/internal_modules/roc_packet/router.h b/src/internal_modules/roc_packet/router.h index dbcc4dc1c3..5c92110f1c 100644 --- a/src/internal_modules/roc_packet/router.h +++ b/src/internal_modules/roc_packet/router.h @@ -37,7 +37,7 @@ class Router : public IWriter, public core::NonCopyable<> { //! Write next packet. //! @remarks //! Route @p packet to a writer or drop it if no routes found. - virtual void write(const PacketPtr& packet); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const PacketPtr& packet); private: struct Route { diff --git a/src/internal_modules/roc_packet/shipper.cpp b/src/internal_modules/roc_packet/shipper.cpp new file mode 100644 index 0000000000..0d11f3afae --- /dev/null +++ b/src/internal_modules/roc_packet/shipper.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "roc_packet/shipper.h" + +namespace roc { +namespace packet { + +Shipper::Shipper(const address::SocketAddr& address, IComposer& composer, IWriter& writer) + : address_(address) + , composer_(composer) + , writer_(writer) { +} + +status::StatusCode Shipper::write(const PacketPtr& packet) { + if (address_.has_host_port()) { + packet->add_flags(Packet::FlagUDP); + packet->udp()->dst_addr = address_; + } + + if ((packet->flags() & Packet::FlagComposed) == 0) { + if (!composer_.compose(*packet)) { + roc_panic("shipper: can't compose packet"); + } + packet->add_flags(Packet::FlagComposed); + } + + return writer_.write(packet); +} + +} // namespace packet +} // namespace roc diff --git a/src/internal_modules/roc_packet/shipper.h b/src/internal_modules/roc_packet/shipper.h new file mode 100644 index 0000000000..da72bb407c --- /dev/null +++ b/src/internal_modules/roc_packet/shipper.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +//! @file roc_packet/shipper.h +//! @brief Prepare and ship outgoing packets. + +#ifndef ROC_PACKET_SHIPPER_H_ +#define ROC_PACKET_SHIPPER_H_ + +#include "roc_address/socket_addr.h" +#include "roc_core/noncopyable.h" +#include "roc_packet/icomposer.h" +#include "roc_packet/iwriter.h" + +namespace roc { +namespace packet { + +//! Prepare a packet for being sent. +class Shipper : public IWriter, public core::NonCopyable<> { +public: + //! Initialize. + //! - @p address - address that is assigned to a packet. + //! - @p composer to compose a packet if necessary. + //! - @p writer to write outgoing packet. + Shipper(const address::SocketAddr& address, IComposer& composer, IWriter& writer); + + //! Write outgoing packet. + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr& packet); + +private: + const address::SocketAddr address_; + + IComposer& composer_; + IWriter& writer_; +}; + +} // namespace packet +} // namespace roc + +#endif // ROC_PACKET_SHIPPER_H_ diff --git a/src/internal_modules/roc_packet/sorted_queue.cpp b/src/internal_modules/roc_packet/sorted_queue.cpp index 409eef50da..61606b473c 100644 --- a/src/internal_modules/roc_packet/sorted_queue.cpp +++ b/src/internal_modules/roc_packet/sorted_queue.cpp @@ -28,7 +28,7 @@ status::StatusCode SortedQueue::read(PacketPtr& packet) { return status::StatusNoData; } -void SortedQueue::write(const PacketPtr& packet) { +status::StatusCode SortedQueue::write(const PacketPtr& packet) { if (!packet) { roc_panic("sorted queue: attempting to add null packet"); } @@ -38,7 +38,8 @@ void SortedQueue::write(const PacketPtr& packet) { "sorted queue: queue is full, dropping packet:" " max_size=%u", (unsigned)max_size_); - return; + // TODO: return StatusAgain (gh-183) + return status::StatusNoData; } if (!latest_ || latest_->compare(*packet) <= 0) { @@ -56,7 +57,8 @@ void SortedQueue::write(const PacketPtr& packet) { if (cmp == 0) { roc_log(LogDebug, "sorted queue: dropping duplicate packet"); - return; + // TODO: return StatusBadArg (gh-183) + return status::StatusNoData; } break; @@ -67,6 +69,8 @@ void SortedQueue::write(const PacketPtr& packet) { } else { list_.push_back(*packet); } + + return status::StatusOK; } size_t SortedQueue::size() const { diff --git a/src/internal_modules/roc_packet/sorted_queue.h b/src/internal_modules/roc_packet/sorted_queue.h index 18a25cd789..7a2cbedf12 100644 --- a/src/internal_modules/roc_packet/sorted_queue.h +++ b/src/internal_modules/roc_packet/sorted_queue.h @@ -36,7 +36,7 @@ class SortedQueue : public IWriter, public IReader, public core::NonCopyable<> { //! - if the maximum queue size is reached, packet is dropped //! - if packet is equal to another packet in the queue, it is dropped //! - otherwise, packet is inserted into the queue, keeping the queue sorted - virtual void write(const PacketPtr& packet); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const PacketPtr& packet); //! Read next packet. //! diff --git a/src/internal_modules/roc_pipeline/receiver_endpoint.cpp b/src/internal_modules/roc_pipeline/receiver_endpoint.cpp index 59ad4e4bdc..1683f90b7c 100644 --- a/src/internal_modules/roc_pipeline/receiver_endpoint.cpp +++ b/src/internal_modules/roc_pipeline/receiver_endpoint.cpp @@ -18,13 +18,13 @@ namespace pipeline { ReceiverEndpoint::ReceiverEndpoint(address::Protocol proto, ReceiverState& receiver_state, - ReceiverSessionGroup& session_group, + packet::IWriter& writer, const rtp::FormatMap& format_map, core::IArena& arena) : core::RefCounted(arena) , proto_(proto) , receiver_state_(receiver_state) - , session_group_(session_group) + , writer_(writer) , parser_(NULL) { packet::IParser* parser = NULL; @@ -118,7 +118,7 @@ packet::IWriter& ReceiverEndpoint::writer() { return *this; } -void ReceiverEndpoint::pull_packets() { +status::StatusCode ReceiverEndpoint::pull_packets() { roc_panic_if(!is_valid()); // Using try_pop_front_exclusive() makes this method lock-free and wait-free. @@ -131,13 +131,20 @@ void ReceiverEndpoint::pull_packets() { continue; } - session_group_.route_packet(packet); - + const status::StatusCode code = writer_.write(packet); receiver_state_.add_pending_packets(-1); + if (code != status::StatusOK) { + // TODO: handle returned status code (gh-183). + if (code != status::StatusNoData) { + return code; + } + } } + + return status::StatusOK; } -void ReceiverEndpoint::write(const packet::PacketPtr& packet) { +status::StatusCode ReceiverEndpoint::write(const packet::PacketPtr& packet) { roc_panic_if(!is_valid()); if (!packet) { @@ -147,6 +154,8 @@ void ReceiverEndpoint::write(const packet::PacketPtr& packet) { receiver_state_.add_pending_packets(+1); queue_.push_back(*packet); + + return status::StatusOK; } } // namespace pipeline diff --git a/src/internal_modules/roc_pipeline/receiver_endpoint.h b/src/internal_modules/roc_pipeline/receiver_endpoint.h index 25dcb44f5f..8fff75c45d 100644 --- a/src/internal_modules/roc_pipeline/receiver_endpoint.h +++ b/src/internal_modules/roc_pipeline/receiver_endpoint.h @@ -22,7 +22,6 @@ #include "roc_packet/iparser.h" #include "roc_packet/iwriter.h" #include "roc_pipeline/config.h" -#include "roc_pipeline/receiver_session_group.h" #include "roc_pipeline/receiver_state.h" #include "roc_rtcp/parser.h" #include "roc_rtp/format_map.h" @@ -41,9 +40,10 @@ class ReceiverEndpoint : public core::RefCountedudp(); if (!udp) { - return false; + // TODO: return StatusBadArg (gh-183) + return status::StatusNoData; } if (udp->src_addr != src_address_) { - return false; + // TODO: return StatusBadArg (gh-183) + return status::StatusNoData; } - queue_router_->write(packet); - return true; + const status::StatusCode code = queue_router_->write(packet); + if (code != status::StatusOK) { + // TODO: return a real status (gh-183) + if (code == status::StatusNoData) { + return status::StatusOK; + } + roc_panic_if_msg(code != status::StatusNoData, + "session: failed to write packet: status=%s", + status::code_to_str(code)); + } + + return status::StatusOK; } bool ReceiverSession::refresh(core::nanoseconds_t current_time, diff --git a/src/internal_modules/roc_pipeline/receiver_session.h b/src/internal_modules/roc_pipeline/receiver_session.h index e078dc5d18..dd8286b2dc 100644 --- a/src/internal_modules/roc_pipeline/receiver_session.h +++ b/src/internal_modules/roc_pipeline/receiver_session.h @@ -33,6 +33,7 @@ #include "roc_packet/delayed_reader.h" #include "roc_packet/iparser.h" #include "roc_packet/ireader.h" +#include "roc_packet/iwriter.h" #include "roc_packet/packet.h" #include "roc_packet/packet_factory.h" #include "roc_packet/router.h" @@ -55,7 +56,8 @@ namespace pipeline { //! - a pipeline for processing packets from single sender and converting //! them into audio frames class ReceiverSession : public core::RefCounted, - public core::ListNode { + public core::ListNode, + public packet::IWriter { public: //! Initialize. ReceiverSession(const ReceiverSessionConfig& session_config, @@ -71,9 +73,7 @@ class ReceiverSession : public core::RefCountedrtcp()) { - route_control_packet_(packet); - return; + return route_control_packet_(packet); } - route_transport_packet_(packet); + return route_transport_packet_(packet); } core::nanoseconds_t @@ -153,21 +153,32 @@ void ReceiverSessionGroup::on_add_link_metrics(const rtcp::LinkMetrics& metrics) } } -void ReceiverSessionGroup::route_transport_packet_(const packet::PacketPtr& packet) { +status::StatusCode +ReceiverSessionGroup::route_transport_packet_(const packet::PacketPtr& packet) { core::SharedPtr sess; for (sess = sessions_.front(); sess; sess = sessions_.nextof(*sess)) { - if (sess->handle(packet)) { - return; + const status::StatusCode code = sess->write(packet); + if (code == status::StatusOK) { + return code; } + + // TODO: handle returned status code (gh-183). + roc_panic_if_msg(code != status::StatusNoData, + "session group: failed to write transport packet: status=%s", + status::code_to_str(code)); } - if (can_create_session_(packet)) { - create_session_(packet); + if (!can_create_session_(packet)) { + // TODO: return StatusBadArg (gh-183) + return status::StatusNoData; } + + return create_session_(packet); } -void ReceiverSessionGroup::route_control_packet_(const packet::PacketPtr& packet) { +status::StatusCode +ReceiverSessionGroup::route_control_packet_(const packet::PacketPtr& packet) { if (!rtcp_composer_) { rtcp_composer_.reset(new (rtcp_composer_) rtcp::Composer()); } @@ -178,11 +189,12 @@ void ReceiverSessionGroup::route_control_packet_(const packet::PacketPtr& packet } if (!rtcp_session_->is_valid()) { - return; + // TODO: return StatusDead (gh-183) + return status::StatusNoData; } // This will invoke IReceiverController methods implemented by us. - rtcp_session_->process_packet(packet); + return rtcp_session_->write(packet); } bool ReceiverSessionGroup::can_create_session_(const packet::PacketPtr& packet) { @@ -194,17 +206,20 @@ bool ReceiverSessionGroup::can_create_session_(const packet::PacketPtr& packet) return true; } -void ReceiverSessionGroup::create_session_(const packet::PacketPtr& packet) { +status::StatusCode +ReceiverSessionGroup::create_session_(const packet::PacketPtr& packet) { if (!packet->udp()) { roc_log(LogError, "session group: can't create session, unexpected non-udp packet"); - return; + // TODO: return StatusBadArg (gh-183) + return status::StatusNoData; } if (!packet->rtp()) { roc_log(LogError, "session group: can't create session, unexpected non-rtp packet"); - return; + // TODO: return StatusBadArg (gh-183) + return status::StatusNoData; } const ReceiverSessionConfig sess_config = make_session_config_(packet); @@ -222,19 +237,25 @@ void ReceiverSessionGroup::create_session_(const packet::PacketPtr& packet) { if (!sess || !sess->is_valid()) { roc_log(LogError, "session group: can't create session, initialization failed"); - return; + // TODO: return StatusNoMem (gh-183) + return status::StatusNoData; } - if (!sess->handle(packet)) { - roc_log(LogError, - "session group: can't create session, can't handle first packet"); - return; + const status::StatusCode code = sess->write(packet); + if (code != status::StatusOK) { + roc_log( + LogError, + "session group: can't create session, can't handle first packet: status=%s", + status::code_to_str(code)); + return code; } mixer_.add_input(sess->reader()); sessions_.push_back(*sess); receiver_state_.add_sessions(+1); + + return status::StatusOK; } void ReceiverSessionGroup::remove_session_(ReceiverSession& sess) { diff --git a/src/internal_modules/roc_pipeline/receiver_session_group.h b/src/internal_modules/roc_pipeline/receiver_session_group.h index c213872717..3b573574a4 100644 --- a/src/internal_modules/roc_pipeline/receiver_session_group.h +++ b/src/internal_modules/roc_pipeline/receiver_session_group.h @@ -16,6 +16,7 @@ #include "roc_core/iarena.h" #include "roc_core/list.h" #include "roc_core/noncopyable.h" +#include "roc_packet/iwriter.h" #include "roc_pipeline/metrics.h" #include "roc_pipeline/receiver_session.h" #include "roc_pipeline/receiver_state.h" @@ -29,7 +30,9 @@ namespace pipeline { //! //! Contains: //! - a set of related receiver sessions -class ReceiverSessionGroup : public core::NonCopyable<>, private rtcp::IReceiverHooks { +class ReceiverSessionGroup : public packet::IWriter, + public core::NonCopyable<>, + private rtcp::IReceiverHooks { public: //! Initialize. ReceiverSessionGroup(const ReceiverConfig& receiver_config, @@ -44,7 +47,7 @@ class ReceiverSessionGroup : public core::NonCopyable<>, private rtcp::IReceiver ~ReceiverSessionGroup(); //! Route packet to session. - void route_packet(const packet::PacketPtr& packet); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr& packet); //! Refresh pipeline according to current time. //! @returns @@ -79,12 +82,12 @@ class ReceiverSessionGroup : public core::NonCopyable<>, private rtcp::IReceiver virtual void on_add_sending_metrics(const rtcp::SendingMetrics& metrics); virtual void on_add_link_metrics(const rtcp::LinkMetrics& metrics); - void route_transport_packet_(const packet::PacketPtr& packet); - void route_control_packet_(const packet::PacketPtr& packet); + status::StatusCode route_transport_packet_(const packet::PacketPtr& packet); + status::StatusCode route_control_packet_(const packet::PacketPtr& packet); bool can_create_session_(const packet::PacketPtr& packet); - void create_session_(const packet::PacketPtr& packet); + status::StatusCode create_session_(const packet::PacketPtr& packet); void remove_session_(ReceiverSession& sess); void remove_all_sessions_(); diff --git a/src/internal_modules/roc_pipeline/receiver_slot.cpp b/src/internal_modules/roc_pipeline/receiver_slot.cpp index 19288ec18b..6a878bfc85 100644 --- a/src/internal_modules/roc_pipeline/receiver_slot.cpp +++ b/src/internal_modules/roc_pipeline/receiver_slot.cpp @@ -9,6 +9,7 @@ #include "roc_pipeline/receiver_slot.h" #include "roc_core/log.h" #include "roc_pipeline/endpoint_helpers.h" +#include "roc_status/code_to_str.h" namespace roc { namespace pipeline { @@ -60,15 +61,27 @@ ReceiverEndpoint* ReceiverSlot::add_endpoint(address::Interface iface, core::nanoseconds_t ReceiverSlot::refresh(core::nanoseconds_t current_time) { if (source_endpoint_) { - source_endpoint_->pull_packets(); + const status::StatusCode code = source_endpoint_->pull_packets(); + if (code != status::StatusOK) { + roc_log(LogError, "receiver slot: failed to pull source endpoint: status=%s", + status::code_to_str(code)); + } } if (repair_endpoint_) { - repair_endpoint_->pull_packets(); + const status::StatusCode code = repair_endpoint_->pull_packets(); + if (code != status::StatusOK) { + roc_log(LogError, "receiver slot: failed to pull repair endpoint: status=%s", + status::code_to_str(code)); + } } if (control_endpoint_) { - control_endpoint_->pull_packets(); + const status::StatusCode code = control_endpoint_->pull_packets(); + if (code != status::StatusOK) { + roc_log(LogError, "receiver slot: failed to pull control endpoint: status=%s", + status::code_to_str(code)); + } } return session_group_.refresh_sessions(current_time); diff --git a/src/internal_modules/roc_pipeline/sender_endpoint.cpp b/src/internal_modules/roc_pipeline/sender_endpoint.cpp index 907c884941..fec62a0758 100644 --- a/src/internal_modules/roc_pipeline/sender_endpoint.cpp +++ b/src/internal_modules/roc_pipeline/sender_endpoint.cpp @@ -11,6 +11,8 @@ #include "roc_core/panic.h" #include "roc_fec/composer.h" #include "roc_fec/headers.h" +#include "roc_packet/shipper.h" +#include "roc_status/status_code.h" namespace roc { namespace pipeline { @@ -20,8 +22,6 @@ SenderEndpoint::SenderEndpoint(address::Protocol proto, packet::IWriter& dest_writer, core::IArena& arena) : proto_(proto) - , dst_writer_(dest_writer) - , dst_address_(dest_address) , composer_(NULL) { packet::IComposer* composer = NULL; @@ -99,10 +99,16 @@ SenderEndpoint::SenderEndpoint(address::Protocol proto, } composer_ = composer; + if (!composer_) { + return; + } + + writer_.reset(new (arena) packet::Shipper(dest_address, *composer_, dest_writer), + arena); } bool SenderEndpoint::is_valid() const { - return composer_; + return composer_ && writer_; } address::Protocol SenderEndpoint::proto() const { @@ -120,25 +126,7 @@ packet::IComposer& SenderEndpoint::composer() { packet::IWriter& SenderEndpoint::writer() { roc_panic_if(!is_valid()); - return *this; -} - -void SenderEndpoint::write(const packet::PacketPtr& packet) { - roc_panic_if(!is_valid()); - - if (dst_address_.has_host_port()) { - packet->add_flags(packet::Packet::FlagUDP); - packet->udp()->dst_addr = dst_address_; - } - - if ((packet->flags() & packet::Packet::FlagComposed) == 0) { - if (!composer_->compose(*packet)) { - roc_panic("sender endpoint: can't compose packet"); - } - packet->add_flags(packet::Packet::FlagComposed); - } - - dst_writer_.write(packet); + return *writer_; } } // namespace pipeline diff --git a/src/internal_modules/roc_pipeline/sender_endpoint.h b/src/internal_modules/roc_pipeline/sender_endpoint.h index 452816ac15..53ae014659 100644 --- a/src/internal_modules/roc_pipeline/sender_endpoint.h +++ b/src/internal_modules/roc_pipeline/sender_endpoint.h @@ -30,7 +30,7 @@ namespace pipeline { //! //! Contains: //! - a pipeline for processing packets for single network endpoint -class SenderEndpoint : public core::NonCopyable<>, private packet::IWriter { +class SenderEndpoint : public core::NonCopyable<> { public: //! Initialize. //! - @p dest_address specifies destination address that is assigned to the @@ -59,18 +59,15 @@ class SenderEndpoint : public core::NonCopyable<>, private packet::IWriter { packet::IWriter& writer(); private: - virtual void write(const packet::PacketPtr& packet); - const address::Protocol proto_; - packet::IWriter& dst_writer_; - address::SocketAddr dst_address_; - packet::IComposer* composer_; core::Optional rtp_composer_; core::ScopedPtr fec_composer_; core::Optional rtcp_composer_; + + core::ScopedPtr writer_; }; } // namespace pipeline diff --git a/src/internal_modules/roc_pipeline/sender_session.cpp b/src/internal_modules/roc_pipeline/sender_session.cpp index fb560bf1f8..bedb6ab42e 100644 --- a/src/internal_modules/roc_pipeline/sender_session.cpp +++ b/src/internal_modules/roc_pipeline/sender_session.cpp @@ -11,6 +11,7 @@ #include "roc_core/panic.h" #include "roc_core/time.h" #include "roc_fec/codec_map.h" +#include "roc_status/code_to_str.h" namespace roc { namespace pipeline { @@ -184,7 +185,15 @@ core::nanoseconds_t SenderSession::refresh(core::nanoseconds_t current_time) { } if (timestamp_extractor_ && timestamp_extractor_->has_mapping()) { - rtcp_session_->generate_packets(current_time); + const status::StatusCode code = rtcp_session_->generate_packets(current_time); + if (code != status::StatusOK) { + // TODO: handle returned status code (gh-183). + roc_panic_if_msg( + code != status::StatusNoData, + "sender session: failed to generate packetes for RTCP session: " + "status=%s", + status::code_to_str(code)); + } } return rtcp_session_->generation_deadline(current_time); diff --git a/src/internal_modules/roc_rtcp/session.cpp b/src/internal_modules/roc_rtcp/session.cpp index 199de4b025..ed0d16eef9 100644 --- a/src/internal_modules/roc_rtcp/session.cpp +++ b/src/internal_modules/roc_rtcp/session.cpp @@ -49,18 +49,21 @@ bool Session::is_valid() const { return valid_; } -void Session::process_packet(const packet::PacketPtr& packet) { +status::StatusCode Session::write(const packet::PacketPtr& packet) { roc_panic_if_msg(!packet, "rtcp session: null packet"); roc_panic_if_msg(!packet->rtcp(), "rtcp session: non-rtcp packet"); Traverser traverser(packet->rtcp()->data); if (!traverser.parse()) { roc_log(LogTrace, "rtcp session: can't parse rtcp packet"); - return; + // TODO: return StatusBadArg (gh-183) + return status::StatusNoData; } parse_events_(traverser); parse_reports_(traverser); + + return status::StatusOK; } core::nanoseconds_t Session::generation_deadline(core::nanoseconds_t current_time) { @@ -73,7 +76,7 @@ core::nanoseconds_t Session::generation_deadline(core::nanoseconds_t current_tim return next_deadline_; } -void Session::generate_packets(core::nanoseconds_t current_time) { +status::StatusCode Session::generate_packets(core::nanoseconds_t current_time) { roc_panic_if_msg(!packet_writer_, "rtcp session: packet writer not set"); if (next_deadline_ == 0) { @@ -81,7 +84,8 @@ void Session::generate_packets(core::nanoseconds_t current_time) { } if (next_deadline_ > current_time) { - return; + // TODO: return StatusAgain (gh-183) + return status::StatusNoData; } do { @@ -89,11 +93,13 @@ void Session::generate_packets(core::nanoseconds_t current_time) { next_deadline_ += core::Millisecond * 200; } while (next_deadline_ <= current_time); - packet::PacketPtr packet = generate_packet_(current_time); - - if (packet) { - packet_writer_->write(packet); + packet::PacketPtr packet; + const status::StatusCode code = generate_packet_(current_time, packet); + if (code != status::StatusOK) { + return code; } + + return packet_writer_->write(packet); } void Session::parse_events_(const Traverser& traverser) { @@ -223,28 +229,28 @@ void Session::parse_reception_block_(const header::ReceptionReportBlock& blk) { } } -packet::PacketPtr Session::generate_packet_(core::nanoseconds_t current_time) { - packet::PacketPtr packet = packet_factory_.new_packet(); +status::StatusCode Session::generate_packet_(core::nanoseconds_t current_time, + packet::PacketPtr& packet) { + packet = packet_factory_.new_packet(); if (!packet) { roc_log(LogError, "rtcp session: can't create packet"); - return NULL; + // TODO: return StatusNoMem (gh-183) + return status::StatusNoData; } // will hold composed RTCP packet core::Slice rtcp_data = buffer_factory_.new_buffer(); if (!rtcp_data) { roc_log(LogError, "rtcp session: can't create buffer"); - return NULL; + // TODO: return StatusNoMem (gh-183) + return status::StatusNoData; } // reset slice rtcp_data.reslice(0, 0); // fill RTCP packet - if (!build_packet_(rtcp_data, current_time)) { - roc_log(LogError, "rtcp session: can't build packet"); - return NULL; - } + build_packet_(rtcp_data, current_time); // will hold whole packet data; if RTCP composer is nested into another // composer, packet_data may hold additionals headers or footers around @@ -253,7 +259,8 @@ packet::PacketPtr Session::generate_packet_(core::nanoseconds_t current_time) { core::Slice packet_data = buffer_factory_.new_buffer(); if (!packet_data) { roc_log(LogError, "rtcp session: can't create buffer"); - return NULL; + // TODO: return StatusNoMem (gh-183) + return status::StatusNoData; } // reset slice @@ -262,7 +269,8 @@ packet::PacketPtr Session::generate_packet_(core::nanoseconds_t current_time) { // prepare packet to be able to hold our RTCP packet if (!packet_composer_.prepare(*packet, packet_data, rtcp_data.size())) { roc_log(LogError, "rtcp session: can't prepare packet"); - return NULL; + // TODO: return StatusInvalidState|StatusDead (gh-183) + return status::StatusNoData; } // attach prepared packet data to the packet @@ -273,16 +281,17 @@ packet::PacketPtr Session::generate_packet_(core::nanoseconds_t current_time) { if (!packet->rtcp() || !packet->rtcp()->data || packet->rtcp()->data.size() != rtcp_data.size()) { roc_log(LogError, "rtcp session: composer prepared invalid packet"); - return NULL; + // TODO: return StatusInvalidState|StatusDead (gh-183) + return status::StatusNoData; } // copy our RTCP packet into that sub-slice memcpy(packet->rtcp()->data.data(), rtcp_data.data(), rtcp_data.size()); - return packet; + return status::StatusOK; } -bool Session::build_packet_(core::Slice& data, core::nanoseconds_t report_time) { +void Session::build_packet_(core::Slice& data, core::nanoseconds_t report_time) { Builder bld(data); if (send_hooks_) { @@ -294,8 +303,6 @@ bool Session::build_packet_(core::Slice& data, core::nanoseconds_t repo } build_session_description_(bld); - - return true; } void Session::build_sender_report_(Builder& bld, core::nanoseconds_t report_time) { diff --git a/src/internal_modules/roc_rtcp/session.h b/src/internal_modules/roc_rtcp/session.h index c324e6ac27..2676b8af30 100644 --- a/src/internal_modules/roc_rtcp/session.h +++ b/src/internal_modules/roc_rtcp/session.h @@ -29,7 +29,7 @@ namespace rtcp { //! RTCP session. //! Processes incoming RTCP packets and generates outgoing RTCP packets. -class Session { +class Session : public packet::IWriter { public: //! Initialize. Session(IReceiverHooks* recv_hooks, @@ -44,7 +44,7 @@ class Session { //! Parse and process incoming packet. //! Invokes session hooks methods during processing. - void process_packet(const packet::PacketPtr& packet); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr& packet); //! When we should generate packets next time. //! Returns absolute time. @@ -54,7 +54,8 @@ class Session { //! Generate and send packet(s). //! Should be called accroding to generation_deadline(). //! @p current_time is current time in nanoseconds since Unix epoch. - void generate_packets(core::nanoseconds_t current_time); + status::StatusCode ROC_ATTR_NODISCARD + generate_packets(core::nanoseconds_t current_time); private: void parse_events_(const Traverser& traverser); @@ -66,9 +67,10 @@ class Session { void parse_receiver_report_(const header::ReceiverReportPacket& rr); void parse_reception_block_(const header::ReceptionReportBlock& blk); - packet::PacketPtr generate_packet_(core::nanoseconds_t current_time); + status::StatusCode generate_packet_(core::nanoseconds_t current_time, + packet::PacketPtr& packet); - bool build_packet_(core::Slice& data, core::nanoseconds_t report_time); + void build_packet_(core::Slice& data, core::nanoseconds_t report_time); void build_sender_report_(Builder& bld, core::nanoseconds_t report_time); void build_receiver_report_(Builder& bld, core::nanoseconds_t report_time); header::ReceptionReportBlock build_reception_block_(const ReceptionMetrics& metrics); diff --git a/src/internal_modules/roc_rtp/timestamp_extractor.cpp b/src/internal_modules/roc_rtp/timestamp_extractor.cpp index 5c18eb1179..6f0a83f5e2 100644 --- a/src/internal_modules/roc_rtp/timestamp_extractor.cpp +++ b/src/internal_modules/roc_rtp/timestamp_extractor.cpp @@ -32,7 +32,7 @@ TimestampExtractor::TimestampExtractor(packet::IWriter& writer, TimestampExtractor::~TimestampExtractor() { } -void TimestampExtractor::write(const packet::PacketPtr& pkt) { +status::StatusCode TimestampExtractor::write(const packet::PacketPtr& pkt) { if (!pkt) { roc_panic("timestamp extractor: unexpected null packet"); } @@ -52,7 +52,7 @@ void TimestampExtractor::write(const packet::PacketPtr& pkt) { rtp_ts_ = pkt->rtp()->stream_timestamp; } - writer_.write(pkt); + return writer_.write(pkt); } bool TimestampExtractor::has_mapping() { diff --git a/src/internal_modules/roc_rtp/timestamp_extractor.h b/src/internal_modules/roc_rtp/timestamp_extractor.h index 0e01e320dd..9af72c2876 100644 --- a/src/internal_modules/roc_rtp/timestamp_extractor.h +++ b/src/internal_modules/roc_rtp/timestamp_extractor.h @@ -33,7 +33,7 @@ class TimestampExtractor : public packet::IWriter, public core::NonCopyable<> { virtual ~TimestampExtractor(); //! Passes pkt downstream and remembers its capture and rtp timestamps. - virtual void write(const packet::PacketPtr& pkt); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr& pkt); //! Check if mapping already available. bool has_mapping(); diff --git a/src/public_api/src/receiver_decoder.cpp b/src/public_api/src/receiver_decoder.cpp index 76de2d64c0..a16e9adddb 100644 --- a/src/public_api/src/receiver_decoder.cpp +++ b/src/public_api/src/receiver_decoder.cpp @@ -16,6 +16,7 @@ #include "roc_core/slice.h" #include "roc_core/stddefs.h" #include "roc_node/receiver_decoder.h" +#include "roc_status/code_to_str.h" using namespace roc; @@ -197,8 +198,16 @@ int roc_receiver_decoder_push(roc_receiver_decoder* decoder, imp_packet->add_flags(packet::Packet::FlagUDP); imp_packet->set_data(imp_slice); - if (!imp_decoder->write(imp_iface, imp_packet)) { - roc_log(LogError, "roc_receiver_decoder_push(): can't write packet to decoder"); + const status::StatusCode code = imp_decoder->write(imp_iface, imp_packet); + if (code != status::StatusOK) { + // TODO: forward status code to user (gh-183) + if (code != status::StatusNoData) { + roc_log( + LogError, + "roc_receiver_decoder_push(): can't write packet to decoder: status=%s", + status::code_to_str(code)); + } + return -1; } diff --git a/src/tests/public_api/test_helpers/proxy.h b/src/tests/public_api/test_helpers/proxy.h index d8a9c556cd..e64b7ef69e 100644 --- a/src/tests/public_api/test_helpers/proxy.h +++ b/src/tests/public_api/test_helpers/proxy.h @@ -18,6 +18,7 @@ #include "roc_netio/network_loop.h" #include "roc_packet/packet_factory.h" #include "roc_packet/queue.h" +#include "roc_status/status_code.h" #include "roc/endpoint.h" @@ -119,47 +120,66 @@ class Proxy : private packet::IWriter { } private: - virtual void write(const packet::PacketPtr& pp) { + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr& pp) { pp->udp()->src_addr = send_config_.bind_address; if (pp->udp()->dst_addr == recv_source_config_.bind_address) { pp->udp()->dst_addr = receiver_source_endp_; - source_queue_.write(pp); + + const status::StatusCode code = source_queue_.write(pp); + if (code != status::StatusOK) { + return code; + } } else { pp->udp()->dst_addr = receiver_repair_endp_; - repair_queue_.write(pp); + + const status::StatusCode code = repair_queue_.write(pp); + if (code != status::StatusOK) { + return code; + } } for (;;) { const size_t block_pos = pos_ % (n_source_packets_ + n_repair_packets_); if (block_pos < n_source_packets_) { - if (!send_packet_(source_queue_, block_pos == 1)) { - return; + const status::StatusCode code = + send_packet_(source_queue_, block_pos == 1); + if (code != status::StatusOK) { + if (code == status::StatusNoData) { + break; + } + return code; } } else { - if (!send_packet_(repair_queue_, false)) { - return; + const status::StatusCode code = send_packet_(repair_queue_, false); + if (code != status::StatusOK) { + if (code == status::StatusNoData) { + break; + } + return code; } } } + + return status::StatusOK; } - bool send_packet_(packet::IReader& reader, bool drop) { + status::StatusCode send_packet_(packet::IReader& reader, bool drop) { packet::PacketPtr pp; - const status::StatusCode code = reader.read(pp); + status::StatusCode code = reader.read(pp); if (code != status::StatusOK) { CHECK(!pp); - return false; + return code; } UNSIGNED_LONGS_EQUAL(status::StatusOK, code); CHECK(pp); pos_++; if (!drop) { - writer_->write(pp); + code = writer_->write(pp); } - return true; + return code; } netio::UdpSenderConfig send_config_; diff --git a/src/tests/roc_audio/test_depacketizer.cpp b/src/tests/roc_audio/test_depacketizer.cpp index a63581044f..cc541873bc 100644 --- a/src/tests/roc_audio/test_depacketizer.cpp +++ b/src/tests/roc_audio/test_depacketizer.cpp @@ -179,7 +179,8 @@ TEST(depacketizer, one_packet_one_read) { Depacketizer dp(queue, decoder, SampleSpecs, false); CHECK(dp.is_valid()); - queue.write(new_packet(encoder, 0, 0.11f, Now)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, 0, 0.11f, Now))); expect_output(dp, SamplesPerPacket, 0.11f, Now); } @@ -192,7 +193,8 @@ TEST(depacketizer, one_packet_multiple_reads) { Depacketizer dp(queue, decoder, SampleSpecs, false); CHECK(dp.is_valid()); - queue.write(new_packet(encoder, 0, 0.11f, Now)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, 0, 0.11f, Now))); core::nanoseconds_t ts = Now; for (size_t n = 0; n < SamplesPerPacket; n++) { @@ -213,7 +215,9 @@ TEST(depacketizer, multiple_packets_one_read) { core::nanoseconds_t ts = Now; for (packet::stream_timestamp_t n = 0; n < NumPackets; n++) { - queue.write(new_packet(encoder, n * SamplesPerPacket, 0.11f, ts)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + queue.write(new_packet(encoder, n * SamplesPerPacket, 0.11f, ts))); ts += NsPerPacket; } @@ -233,18 +237,24 @@ TEST(depacketizer, multiple_packets_multiple_reads) { CHECK(dp.is_valid()); // Start with a packet with zero capture timestamp. - queue.write(new_packet(encoder, 0, 0.01f, 0)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(new_packet(encoder, 0, 0.01f, 0))); const size_t samples_per_frame = SamplesPerPacket / FramesPerPacket; for (size_t n = 0; n < FramesPerPacket; n++) { expect_output(dp, samples_per_frame, 0.01f, 0); } core::nanoseconds_t ts = Now; - queue.write(new_packet(encoder, 1 * SamplesPerPacket, 0.11f, ts)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + queue.write(new_packet(encoder, 1 * SamplesPerPacket, 0.11f, ts))); ts += NsPerPacket; - queue.write(new_packet(encoder, 2 * SamplesPerPacket, 0.22f, ts)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + queue.write(new_packet(encoder, 2 * SamplesPerPacket, 0.22f, ts))); ts += NsPerPacket; - queue.write(new_packet(encoder, 3 * SamplesPerPacket, 0.33f, ts)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + queue.write(new_packet(encoder, 3 * SamplesPerPacket, 0.33f, ts))); ts = Now; for (size_t n = 0; n < FramesPerPacket; n++) { @@ -276,11 +286,14 @@ TEST(depacketizer, timestamp_overflow) { const packet::stream_timestamp_t ts3 = ts2 + SamplesPerPacket; core::nanoseconds_t ts = Now; - queue.write(new_packet(encoder, ts1, 0.11f, ts)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts1, 0.11f, ts))); ts += NsPerPacket; - queue.write(new_packet(encoder, ts2, 0.22f, ts)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts2, 0.22f, ts))); ts += NsPerPacket; - queue.write(new_packet(encoder, ts3, 0.33f, ts)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts3, 0.33f, ts))); ts = Now; expect_output(dp, SamplesPerPacket, 0.11f, ts); @@ -305,9 +318,12 @@ TEST(depacketizer, drop_late_packets) { const core::nanoseconds_t capt_ts2 = Now; const core::nanoseconds_t capt_ts3 = ts1 + NsPerPacket; - queue.write(new_packet(encoder, ts1, 0.11f, capt_ts1)); - queue.write(new_packet(encoder, ts2, 0.22f, capt_ts2)); - queue.write(new_packet(encoder, ts3, 0.33f, capt_ts3)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts1, 0.11f, capt_ts1))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts2, 0.22f, capt_ts2))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts3, 0.33f, capt_ts3))); expect_output(dp, SamplesPerPacket, 0.11f, capt_ts1); expect_output(dp, SamplesPerPacket, 0.33f, capt_ts3); @@ -328,9 +344,12 @@ TEST(depacketizer, drop_late_packets_timestamp_overflow) { const core::nanoseconds_t capt_ts2 = Now - NsPerPacket; const core::nanoseconds_t capt_ts3 = Now + NsPerPacket; - queue.write(new_packet(encoder, ts1, 0.11f, capt_ts1)); - queue.write(new_packet(encoder, ts2, 0.22f, capt_ts2)); - queue.write(new_packet(encoder, ts3, 0.33f, capt_ts3)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts1, 0.11f, capt_ts1))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts2, 0.22f, capt_ts2))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts3, 0.33f, capt_ts3))); expect_output(dp, SamplesPerPacket, 0.11f, capt_ts1); expect_output(dp, SamplesPerPacket, 0.33f, capt_ts3); @@ -355,7 +374,7 @@ TEST(depacketizer, zeros_no_next_packet) { Depacketizer dp(queue, decoder, SampleSpecs, false); CHECK(dp.is_valid()); - queue.write(new_packet(encoder, 0, 0.11f, 0)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(new_packet(encoder, 0, 0.11f, 0))); expect_output(dp, SamplesPerPacket, 0.11f, 0); expect_output(dp, SamplesPerPacket, 0.00f, 0); // no packet -- no ts @@ -369,8 +388,12 @@ TEST(depacketizer, zeros_between_packets) { Depacketizer dp(queue, decoder, SampleSpecs, false); CHECK(dp.is_valid()); - queue.write(new_packet(encoder, 1 * SamplesPerPacket, 0.11f, Now)); - queue.write(new_packet(encoder, 3 * SamplesPerPacket, 0.33f, Now + NsPerPacket * 2)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + queue.write(new_packet(encoder, 1 * SamplesPerPacket, 0.11f, Now))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, 3 * SamplesPerPacket, 0.33f, + Now + NsPerPacket * 2))); expect_output(dp, SamplesPerPacket, 0.11f, Now); expect_output(dp, SamplesPerPacket, 0.00f, Now + NsPerPacket); @@ -392,8 +415,10 @@ TEST(depacketizer, zeros_between_packets_timestamp_overflow) { const core::nanoseconds_t capt_ts2 = Now; const core::nanoseconds_t capt_ts3 = Now + NsPerPacket; - queue.write(new_packet(encoder, ts1, 0.11f, capt_ts1)); - queue.write(new_packet(encoder, ts3, 0.33f, capt_ts3)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts1, 0.11f, capt_ts1))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts3, 0.33f, capt_ts3))); expect_output(dp, SamplesPerPacket, 0.11f, capt_ts1); expect_output(dp, SamplesPerPacket, 0.000f, capt_ts2); @@ -410,7 +435,8 @@ TEST(depacketizer, zeros_after_packet) { Depacketizer dp(queue, decoder, SampleSpecs, false); CHECK(dp.is_valid()); - queue.write(new_packet(encoder, 0, 0.11f, Now)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, 0, 0.11f, Now))); core::Slice b1 = new_buffer(SamplesPerPacket / 2); core::Slice b2 = new_buffer(SamplesPerPacket); @@ -437,7 +463,8 @@ TEST(depacketizer, packet_after_zeros) { expect_output(dp, SamplesPerPacket, 0.00f, 0); - queue.write(new_packet(encoder, 0, 0.11f, Now)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, 0, 0.11f, Now))); expect_output(dp, SamplesPerPacket, 0.11f, Now); } @@ -456,9 +483,13 @@ TEST(depacketizer, overlapping_packets) { packet::stream_timestamp_t ts2 = SamplesPerPacket / 2; packet::stream_timestamp_t ts3 = SamplesPerPacket; - queue.write(new_packet(encoder, ts1, 0.11f, Now)); - queue.write(new_packet(encoder, ts2, 0.22f, Now + NsPerPacket / 2)); - queue.write(new_packet(encoder, ts3, 0.33f, Now + NsPerPacket)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts1, 0.11f, Now))); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + queue.write(new_packet(encoder, ts2, 0.22f, Now + NsPerPacket / 2))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, ts3, 0.33f, Now + NsPerPacket))); expect_output(dp, SamplesPerPacket, 0.11f, Now); expect_output(dp, SamplesPerPacket / 2, 0.22f, Now + NsPerPacket); @@ -539,7 +570,7 @@ TEST(depacketizer, frame_flags_incompltete_blank) { for (size_t p = 0; p < PacketsPerFrame; p++) { if (packets[n][p] != NULL) { - queue.write(packets[n][p]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(packets[n][p])); } } @@ -574,7 +605,7 @@ TEST(depacketizer, frame_flags_drops) { }; for (size_t n = 0; n < ROC_ARRAY_SIZE(packets); n++) { - queue.write(packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(packets[n])); } for (size_t n = 0; n < ROC_ARRAY_SIZE(frame_flags); n++) { @@ -611,7 +642,9 @@ TEST(depacketizer, timestamp) { capt_ts = Now; for (size_t n = 0; n < NumPackets; n++) { const size_t nsamples = packet::stream_timestamp_t(n * SamplesPerPacket); - queue.write(new_packet(encoder, StartTimestamp + nsamples, 0.1f, capt_ts)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + queue.write(new_packet(encoder, StartTimestamp + nsamples, 0.1f, capt_ts))); capt_ts += SampleSpecs.samples_per_chan_2_ns(SamplesPerPacket); } @@ -654,7 +687,8 @@ TEST(depacketizer, read_after_error) { Depacketizer dp(reader, decoder, SampleSpecs, false); CHECK(dp.is_valid()); - queue.write(new_packet(encoder, 0, 0.11f, Now)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet(encoder, 0, 0.11f, Now))); UNSIGNED_LONGS_EQUAL(0, reader.call_count()); diff --git a/src/tests/roc_fec/test_helpers/packet_dispatcher.h b/src/tests/roc_fec/test_helpers/packet_dispatcher.h index 94df2eced0..c1a5f4d5e7 100644 --- a/src/tests/roc_fec/test_helpers/packet_dispatcher.h +++ b/src/tests/roc_fec/test_helpers/packet_dispatcher.h @@ -45,12 +45,14 @@ class PacketDispatcher : public packet::IWriter { reset(); } - virtual void write(const packet::PacketPtr& p) { + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr& p) { store_(p); if (++packet_num_ >= num_source_ + num_repair_) { packet_num_ = 0; } + + return status::StatusOK; } packet::IReader& source_reader() { @@ -176,9 +178,9 @@ class PacketDispatcher : public packet::IWriter { } if (p->flags() & packet::Packet::FlagAudio) { - source_stock_.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, source_stock_.write(p)); } else if (p->flags() & packet::Packet::FlagRepair) { - repair_stock_.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, repair_stock_.write(p)); } else { FAIL("unexpected packet type"); } @@ -188,9 +190,11 @@ class PacketDispatcher : public packet::IWriter { CHECK(p); if (p->flags() & packet::Packet::FlagAudio) { - source_queue_.write(reparse_packet_(source_parser_, p)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + source_queue_.write(reparse_packet_(source_parser_, p))); } else if (p->flags() & packet::Packet::FlagRepair) { - repair_queue_.write(reparse_packet_(repair_parser_, p)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + repair_queue_.write(reparse_packet_(repair_parser_, p))); } else { FAIL("unexpected packet type"); } diff --git a/src/tests/roc_fec/test_writer_reader.cpp b/src/tests/roc_fec/test_writer_reader.cpp index 8190d92553..f0e2390136 100644 --- a/src/tests/roc_fec/test_writer_reader.cpp +++ b/src/tests/roc_fec/test_writer_reader.cpp @@ -254,7 +254,7 @@ TEST(writer_reader, no_losses) { fill_all_packets(0); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } dispatcher.push_stocks(); @@ -304,7 +304,7 @@ TEST(writer_reader, 1_loss) { dispatcher.lose(11); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } dispatcher.push_stocks(); @@ -353,14 +353,14 @@ TEST(writer_reader, lost_first_packet_in_first_block) { fill_all_packets(0); dispatcher.lose(0); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } // Sending second block lossless. dispatcher.clear_losses(); fill_all_packets(NumSourcePackets); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } dispatcher.push_stocks(); @@ -415,7 +415,7 @@ TEST(writer_reader, lost_one_source_and_all_repair_packets) { } fill_all_packets(0); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } dispatcher.push_stocks(); @@ -424,7 +424,7 @@ TEST(writer_reader, lost_one_source_and_all_repair_packets) { dispatcher.lose(5); fill_all_packets(NumSourcePackets); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } dispatcher.push_stocks(); @@ -491,7 +491,7 @@ TEST(writer_reader, multiple_blocks_1_loss) { fill_all_packets(NumSourcePackets * block_num); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } dispatcher.push_stocks(); @@ -560,7 +560,7 @@ TEST(writer_reader, multiple_blocks_in_queue) { fill_all_packets(NumSourcePackets * block_num); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } } dispatcher.push_stocks(); @@ -620,7 +620,7 @@ TEST(writer_reader, interleaved_packets) { for (size_t i = 0; i < NumPackets; ++i) { many_packets[i] = fill_one_packet(i); - writer.write(many_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(many_packets[i])); } dispatcher.push_stocks(); @@ -672,7 +672,7 @@ TEST(writer_reader, delayed_packets) { fill_all_packets(0); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } CHECK(NumSourcePackets > 10); @@ -753,7 +753,7 @@ TEST(writer_reader, late_out_of_order_packets) { } for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } // Deliver packets 0-6 and 11-20 @@ -830,7 +830,7 @@ TEST(writer_reader, repair_packets_before_source_packets) { // Encode first block. for (size_t i = 0; i < writer_config.n_source_packets; ++i) { - writer.write(fill_one_packet(wr_sn)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(wr_sn))); wr_sn++; } @@ -849,7 +849,7 @@ TEST(writer_reader, repair_packets_before_source_packets) { // Encode second block. for (size_t i = 0; i < writer_config.n_source_packets; ++i) { - writer.write(fill_one_packet(wr_sn)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(wr_sn))); wr_sn++; } @@ -918,7 +918,7 @@ TEST(writer_reader, repair_packets_mixed_with_source_packets) { // Encode first block. for (size_t i = 0; i < writer_config.n_source_packets; ++i) { - writer.write(fill_one_packet(wr_sn)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(wr_sn))); wr_sn++; } @@ -942,7 +942,7 @@ TEST(writer_reader, repair_packets_mixed_with_source_packets) { // Encode second block. for (size_t i = 0; i < writer_config.n_source_packets; ++i) { - writer.write(fill_one_packet(wr_sn)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(wr_sn))); wr_sn++; } @@ -1021,7 +1021,7 @@ TEST(writer_reader, multiple_repair_attempts) { dispatcher.lose(15); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); if (i != 5 && i != 15) { dispatcher.push_source_stock(1); } @@ -1031,7 +1031,7 @@ TEST(writer_reader, multiple_repair_attempts) { fill_all_packets(NumSourcePackets); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); dispatcher.push_source_stock(1); } @@ -1100,19 +1100,19 @@ TEST(writer_reader, drop_outdated_block) { // Send first block. fill_all_packets(NumSourcePackets); for (size_t n = 0; n < NumSourcePackets; ++n) { - writer.write(source_packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[n])); } // Send outdated block. fill_all_packets(0); for (size_t n = 0; n < NumSourcePackets; ++n) { - writer.write(source_packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[n])); } // Send next block. fill_all_packets(NumSourcePackets * 2); for (size_t n = 0; n < NumSourcePackets; ++n) { - writer.write(source_packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[n])); } dispatcher.push_stocks(); @@ -1178,7 +1178,7 @@ TEST(writer_reader, repaired_block_numbering) { dispatcher.lose(lost_packet_n); for (size_t n = 0; n < NumSourcePackets; ++n) { - writer.write(source_packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[n])); } dispatcher.clear_losses(); @@ -1187,7 +1187,7 @@ TEST(writer_reader, repaired_block_numbering) { fill_all_packets(NumSourcePackets); for (size_t n = 0; n < NumSourcePackets; ++n) { - writer.write(source_packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[n])); } dispatcher.push_stocks(); @@ -1267,7 +1267,7 @@ TEST(writer_reader, invalid_esi) { // encode packets and write to queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } // write packets from queue to dispatcher @@ -1290,7 +1290,7 @@ TEST(writer_reader, invalid_esi) { p->fec()->encoding_symbol_id = NumSourcePackets + NumRepairPackets; recompose_packet(p); } - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // deliver packets from dispatcher to reader @@ -1350,7 +1350,7 @@ TEST(writer_reader, invalid_sbl) { // encode packets and write to queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } // write packets from queue to dispatcher @@ -1368,7 +1368,7 @@ TEST(writer_reader, invalid_sbl) { p->fec()->source_block_length = NumSourcePackets + 1; recompose_packet(p); } - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // deliver packets from dispatcher to reader @@ -1428,7 +1428,7 @@ TEST(writer_reader, invalid_nes) { // encode packets and write to queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } // write packets from queue to dispatcher @@ -1446,7 +1446,7 @@ TEST(writer_reader, invalid_nes) { p->fec()->block_length = NumSourcePackets + NumRepairPackets + 1; recompose_packet(p); } - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // deliver packets from dispatcher to reader @@ -1502,7 +1502,7 @@ TEST(writer_reader, invalid_payload_size) { // encode packets and write to writer_queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } // read packets from writer_queue queue, spoil some packets, and @@ -1532,9 +1532,9 @@ TEST(writer_reader, invalid_payload_size) { } if (p->flags() & packet::Packet::FlagRepair) { - repair_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, repair_queue.write(p)); } else { - source_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, source_queue.write(p)); } } @@ -1592,7 +1592,7 @@ TEST(writer_reader, zero_source_packets) { // encode packets and write to queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } // lose source packet #5 @@ -1610,7 +1610,7 @@ TEST(writer_reader, zero_source_packets) { recompose_packet(p); } - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // check we have processed all packets @@ -1677,7 +1677,9 @@ TEST(writer_reader, zero_repair_packets) { for (size_t n_block = 0; n_block < NumBlocks; n_block++) { // encode packets and write to queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(fill_one_packet(i, FECPayloadSize, &ldpc_source_composer)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + writer.write(fill_one_packet( + i, FECPayloadSize, &ldpc_source_composer))); } // lose source packet #5 @@ -1695,7 +1697,7 @@ TEST(writer_reader, zero_repair_packets) { ldpc_repair_composer.compose(*p); } - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // check we have processed all packets @@ -1758,7 +1760,7 @@ TEST(writer_reader, zero_payload_size) { // encode packets and write to writer_queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } // read packets from writer_queue queue, spoil some packets, and @@ -1779,9 +1781,9 @@ TEST(writer_reader, zero_payload_size) { } if (p->flags() & packet::Packet::FlagRepair) { - repair_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, repair_queue.write(p)); } else { - source_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, source_queue.write(p)); } } @@ -1850,7 +1852,7 @@ TEST(writer_reader, sbn_jump) { fill_all_packets(NumSourcePackets * n); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } } @@ -1859,7 +1861,7 @@ TEST(writer_reader, sbn_jump) { packet::PacketPtr p; UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(p)); CHECK(p); - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // deliver packets from dispatcher to reader @@ -1886,7 +1888,7 @@ TEST(writer_reader, sbn_jump) { p->fec()->source_block_number += MaxSbnJump; recompose_packet(p); - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // deliver packets from dispatcher to reader @@ -1913,7 +1915,7 @@ TEST(writer_reader, sbn_jump) { p->fec()->source_block_number += MaxSbnJump * 2 + 1; recompose_packet(p); - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // deliver packets from dispatcher to reader @@ -1971,7 +1973,8 @@ TEST(writer_reader, writer_encode_blocks) { } for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + writer.write(source_packets[i])); } dispatcher.push_stocks(); @@ -2068,7 +2071,7 @@ TEST(writer_reader, writer_resize_blocks) { for (size_t i = 0; i < source_sizes[n]; ++i) { packet::PacketPtr p = fill_one_packet(wr_sn, payload_sizes[n]); wr_sn++; - writer.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(p)); } UNSIGNED_LONGS_EQUAL(source_sizes[n], dispatcher.source_size()); @@ -2139,7 +2142,7 @@ TEST(writer_reader, resize_block_begin) { for (size_t i = 0; i < source_sizes[n]; ++i) { packet::PacketPtr p = fill_one_packet(wr_sn, payload_sizes[n]); wr_sn++; - writer.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(p)); } UNSIGNED_LONGS_EQUAL(source_sizes[n], dispatcher.source_size()); @@ -2224,7 +2227,7 @@ TEST(writer_reader, resize_block_middle) { // Write first half of the packets. for (size_t i = 0; i < prev_sblen / 2; ++i) { - writer.write(packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(packets[i])); } // Update source block size. @@ -2232,7 +2235,7 @@ TEST(writer_reader, resize_block_middle) { // Write the remaining packets. for (size_t i = prev_sblen / 2; i < prev_sblen; ++i) { - writer.write(packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(packets[i])); } UNSIGNED_LONGS_EQUAL(prev_sblen, dispatcher.source_size()); @@ -2315,7 +2318,7 @@ TEST(writer_reader, resize_block_losses) { for (size_t i = 0; i < source_sizes[n]; ++i) { packet::PacketPtr p = fill_one_packet(wr_sn, payload_sizes[n]); wr_sn++; - writer.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(p)); } UNSIGNED_LONGS_EQUAL(source_sizes[n] - 1, dispatcher.source_size()); @@ -2372,7 +2375,7 @@ TEST(writer_reader, resize_block_repair_first) { // Encode first block. for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(fill_one_packet(wr_sn)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(wr_sn))); wr_sn++; } @@ -2398,7 +2401,9 @@ TEST(writer_reader, resize_block_repair_first) { // Encode second block. for (size_t i = 0; i < NumSourcePackets * 2; ++i) { - writer.write(fill_one_packet(wr_sn, FECPayloadSize * 2)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + writer.write(fill_one_packet(wr_sn, FECPayloadSize * 2))); wr_sn++; } @@ -2457,7 +2462,7 @@ TEST(writer_reader, error_writer_resize_block) { CHECK(writer.resize(NumSourcePackets, BlockSize1)); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(fill_one_packet(sn++)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(sn++))); } CHECK(writer.is_alive()); @@ -2472,7 +2477,9 @@ TEST(writer_reader, error_writer_resize_block) { CHECK(writer.resize(NumSourcePackets, BlockSize2)); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(fill_one_packet(sn++)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, + writer.write(fill_one_packet(sn++))); + CHECK(!writer.is_alive()); } @@ -2509,7 +2516,7 @@ TEST(writer_reader, error_writer_encode_packet) { CHECK(writer.resize(BlockSize1, NumRepairPackets)); for (size_t i = 0; i < BlockSize1; ++i) { - writer.write(fill_one_packet(sn++)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(sn++))); } CHECK(writer.is_alive()); @@ -2520,10 +2527,12 @@ TEST(writer_reader, error_writer_encode_packet) { CHECK(writer.resize(BlockSize2, NumRepairPackets)); for (size_t i = 0; i < BlockSize2; ++i) { - writer.write(fill_one_packet(sn++)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, + writer.write(fill_one_packet(sn++))); + + CHECK(!writer.is_alive()); } - CHECK(!writer.is_alive()); CHECK(dispatcher.source_size() == BlockSize1); CHECK(dispatcher.repair_size() == NumRepairPackets); } @@ -2566,7 +2575,7 @@ TEST(writer_reader, error_reader_resize_block) { // write first block CHECK(writer.resize(BlockSize1, NumRepairPackets)); for (size_t i = 0; i < BlockSize1; ++i) { - writer.write(fill_one_packet(sn++)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(sn++))); } // deliver first block @@ -2584,7 +2593,7 @@ TEST(writer_reader, error_reader_resize_block) { // write second block CHECK(writer.resize(BlockSize2, NumRepairPackets)); for (size_t i = 0; i < BlockSize2; ++i) { - writer.write(fill_one_packet(sn++)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(sn++))); } // deliver second block @@ -2639,7 +2648,7 @@ TEST(writer_reader, error_reader_decode_packet) { // write first block CHECK(writer.resize(BlockSize1, NumRepairPackets)); for (size_t i = 0; i < BlockSize1; ++i) { - writer.write(fill_one_packet(sn++)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(sn++))); } // deliver first block @@ -2661,7 +2670,7 @@ TEST(writer_reader, error_reader_decode_packet) { // write second block CHECK(writer.resize(BlockSize2, NumRepairPackets)); for (size_t i = 0; i < BlockSize2; ++i) { - writer.write(fill_one_packet(sn++)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(sn++))); } // deliver second block @@ -2728,7 +2737,7 @@ TEST(writer_reader, writer_oversized_block) { // write packets to dispatcher for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } // deliver packets from dispatcher to reader @@ -2793,7 +2802,9 @@ TEST(writer_reader, reader_oversized_source_block) { // encode packets and write to queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(fill_one_packet(i, FECPayloadSize, &ldpc_source_composer)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + writer.write(fill_one_packet(i, FECPayloadSize, &ldpc_source_composer))); } // write packets from queue to dispatcher @@ -2809,7 +2820,7 @@ TEST(writer_reader, reader_oversized_source_block) { ldpc_source_composer.compose(*p); } - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // deliver packets from dispatcher to reader @@ -2863,7 +2874,9 @@ TEST(writer_reader, reader_oversized_repair_block) { // encode packets and write to queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(fill_one_packet(i, FECPayloadSize, &ldpc_source_composer)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + writer.write(fill_one_packet(i, FECPayloadSize, &ldpc_source_composer))); } // write packets from queue to dispatcher @@ -2879,7 +2892,7 @@ TEST(writer_reader, reader_oversized_repair_block) { ldpc_repair_composer.compose(*p); } - dispatcher.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, dispatcher.write(p)); } // deliver packets from dispatcher to reader @@ -2917,7 +2930,8 @@ TEST(writer_reader, writer_invalid_payload_size_change) { // write the first block with the same payload size for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(fill_one_packet(sn++, FECPayloadSize)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + writer.write(fill_one_packet(sn++, FECPayloadSize))); } CHECK(writer.is_alive()); @@ -2926,7 +2940,8 @@ TEST(writer_reader, writer_invalid_payload_size_change) { // write a half of the second block with another payload size for (size_t i = 0; i < NumSourcePackets / 2; ++i) { - writer.write(fill_one_packet(sn++, FECPayloadSize - 1)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + writer.write(fill_one_packet(sn++, FECPayloadSize - 1))); } CHECK(writer.is_alive()); @@ -2935,7 +2950,8 @@ TEST(writer_reader, writer_invalid_payload_size_change) { UNSIGNED_LONGS_EQUAL(NumRepairPackets, dispatcher.repair_size()); // write a packet with different payload size - writer.write(fill_one_packet(sn, FECPayloadSize)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, + writer.write(fill_one_packet(sn, FECPayloadSize))); // writer should be terminated CHECK(!writer.is_alive()); @@ -2974,7 +2990,7 @@ TEST(writer_reader, reader_invalid_fec_scheme_source_packet) { // encode packets and write to queue for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(fill_one_packet(i)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(i))); } UNSIGNED_LONGS_EQUAL(NumSourcePackets + NumRepairPackets, writer_queue.size()); @@ -2984,7 +3000,7 @@ TEST(writer_reader, reader_invalid_fec_scheme_source_packet) { UNSIGNED_LONGS_EQUAL(status::StatusOK, writer_queue.read(p)); CHECK(p); CHECK((p->flags() & packet::Packet::FlagRepair) == 0); - source_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, source_queue.write(p)); } UNSIGNED_LONGS_EQUAL(NumSourcePackets / 2, source_queue.size()); @@ -3004,7 +3020,7 @@ TEST(writer_reader, reader_invalid_fec_scheme_source_packet) { CHECK((p->flags() & packet::Packet::FlagRepair) == 0); p->fec()->fec_scheme = CodecMap::instance().nth_scheme( (n_scheme + 1) % CodecMap::instance().num_schemes()); - source_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, source_queue.write(p)); UNSIGNED_LONGS_EQUAL(1, source_queue.size()); } @@ -3046,7 +3062,7 @@ TEST(writer_reader, reader_invalid_fec_scheme_repair_packet) { // encode packets and write to queue for (size_t i = 0; i < NumSourcePackets * 2; ++i) { - writer.write(fill_one_packet(i)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(fill_one_packet(i))); } UNSIGNED_LONGS_EQUAL((NumSourcePackets + NumRepairPackets) * 2, writer_queue.size()); @@ -3057,7 +3073,7 @@ TEST(writer_reader, reader_invalid_fec_scheme_repair_packet) { UNSIGNED_LONGS_EQUAL(status::StatusOK, writer_queue.read(p)); CHECK(p); CHECK((p->flags() & packet::Packet::FlagRepair) == 0); - source_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, source_queue.write(p)); } UNSIGNED_LONGS_EQUAL(NumSourcePackets, source_queue.size()); @@ -3067,7 +3083,7 @@ TEST(writer_reader, reader_invalid_fec_scheme_repair_packet) { UNSIGNED_LONGS_EQUAL(status::StatusOK, writer_queue.read(p)); CHECK(p); CHECK((p->flags() & packet::Packet::FlagRepair) != 0); - repair_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, repair_queue.write(p)); } UNSIGNED_LONGS_EQUAL(NumRepairPackets / 2, repair_queue.size()); @@ -3088,7 +3104,7 @@ TEST(writer_reader, reader_invalid_fec_scheme_repair_packet) { CHECK((p->flags() & packet::Packet::FlagRepair) != 0); p->fec()->fec_scheme = CodecMap::instance().nth_scheme( (n_scheme + 1) % CodecMap::instance().num_schemes()); - repair_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, repair_queue.write(p)); UNSIGNED_LONGS_EQUAL(1, repair_queue.size()); } @@ -3106,7 +3122,7 @@ TEST(writer_reader, reader_invalid_fec_scheme_repair_packet) { UNSIGNED_LONGS_EQUAL(status::StatusOK, writer_queue.read(p)); CHECK(p); CHECK((p->flags() & packet::Packet::FlagRepair) == 0); - source_queue.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusOK, source_queue.write(p)); } UNSIGNED_LONGS_EQUAL(NumSourcePackets, source_queue.size()); @@ -3155,7 +3171,7 @@ TEST(writer_reader, failed_to_read_source_packet) { fill_all_packets(0); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } for (size_t i = 0; i < NumSourcePackets + NumRepairPackets; ++i) { @@ -3164,7 +3180,7 @@ TEST(writer_reader, failed_to_read_source_packet) { CHECK(pp); if (pp->flags() & packet::Packet::FlagRepair) { - repair_reader.write(pp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, repair_reader.write(pp)); } } @@ -3205,7 +3221,7 @@ TEST(writer_reader, failed_to_read_repair_packet) { fill_all_packets(0); for (size_t i = 0; i < NumSourcePackets; ++i) { - writer.write(source_packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(source_packets[i])); } for (size_t i = 0; i < NumSourcePackets + NumRepairPackets; ++i) { @@ -3214,7 +3230,7 @@ TEST(writer_reader, failed_to_read_repair_packet) { CHECK(pp); if (pp->flags() & packet::Packet::FlagAudio) { - source_reader.write(pp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, source_reader.write(pp)); } } diff --git a/src/tests/roc_netio/test_udp_io.cpp b/src/tests/roc_netio/test_udp_io.cpp index 2d8783ec4a..9db1a3ec26 100644 --- a/src/tests/roc_netio/test_udp_io.cpp +++ b/src/tests/roc_netio/test_udp_io.cpp @@ -125,7 +125,8 @@ TEST(udp_io, one_sender_one_receiver_single_thread_non_blocking_disabled) { for (int i = 0; i < NumIterations; i++) { for (int p = 0; p < NumPackets; p++) { - tx_writer->write(new_packet(tx_config, rx_config, p)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + tx_writer->write(new_packet(tx_config, rx_config, p))); } for (int p = 0; p < NumPackets; p++) { packet::PacketPtr pp; @@ -152,7 +153,8 @@ TEST(udp_io, one_sender_one_receiver_single_loop) { for (int i = 0; i < NumIterations; i++) { for (int p = 0; p < NumPackets; p++) { - tx_writer->write(new_packet(tx_config, rx_config, p)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + tx_writer->write(new_packet(tx_config, rx_config, p))); } for (int p = 0; p < NumPackets; p++) { packet::PacketPtr pp; @@ -181,7 +183,8 @@ TEST(udp_io, one_sender_one_receiver_separate_loops) { for (int i = 0; i < NumIterations; i++) { for (int p = 0; p < NumPackets; p++) { - tx_writer->write(new_packet(tx_config, rx_config, p)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + tx_writer->write(new_packet(tx_config, rx_config, p))); } for (int p = 0; p < NumPackets; p++) { packet::PacketPtr pp; @@ -220,9 +223,15 @@ TEST(udp_io, one_sender_many_receivers) { for (int i = 0; i < NumIterations; i++) { for (int p = 0; p < NumPackets; p++) { - tx_writer->write(new_packet(tx_config, rx_config1, p * 10)); - tx_writer->write(new_packet(tx_config, rx_config2, p * 20)); - tx_writer->write(new_packet(tx_config, rx_config3, p * 30)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + tx_writer->write(new_packet(tx_config, rx_config1, p * 10))); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + tx_writer->write(new_packet(tx_config, rx_config2, p * 20))); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + tx_writer->write(new_packet(tx_config, rx_config3, p * 30))); } for (int p = 0; p < NumPackets; p++) { packet::PacketPtr pp1; @@ -273,7 +282,9 @@ TEST(udp_io, many_senders_one_receiver) { for (int i = 0; i < NumIterations; i++) { for (int p = 0; p < NumPackets; p++) { - tx_writer1->write(new_packet(tx_config1, rx_config, p * 10)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + tx_writer1->write(new_packet(tx_config1, rx_config, p * 10))); } for (int p = 0; p < NumPackets; p++) { packet::PacketPtr pp; @@ -281,7 +292,9 @@ TEST(udp_io, many_senders_one_receiver) { check_packet(pp, tx_config1, rx_config, p * 10); } for (int p = 0; p < NumPackets; p++) { - tx_writer2->write(new_packet(tx_config2, rx_config, p * 20)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + tx_writer2->write(new_packet(tx_config2, rx_config, p * 20))); } for (int p = 0; p < NumPackets; p++) { packet::PacketPtr pp; @@ -289,7 +302,9 @@ TEST(udp_io, many_senders_one_receiver) { check_packet(pp, tx_config2, rx_config, p * 20); } for (int p = 0; p < NumPackets; p++) { - tx_writer3->write(new_packet(tx_config3, rx_config, p * 30)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + tx_writer3->write(new_packet(tx_config3, rx_config, p * 30))); } for (int p = 0; p < NumPackets; p++) { packet::PacketPtr pp; diff --git a/src/tests/roc_node/test_receiver_decoder.cpp b/src/tests/roc_node/test_receiver_decoder.cpp index fb1a84fc5d..63824518db 100644 --- a/src/tests/roc_node/test_receiver_decoder.cpp +++ b/src/tests/roc_node/test_receiver_decoder.cpp @@ -56,8 +56,10 @@ TEST(receiver_decoder, write) { packet::PacketPtr pp = packet_factory.new_packet(); - CHECK(!receiver_decoder.write(address::Iface_AudioSource, pp)); - CHECK(!receiver_decoder.write(address::Iface_AudioRepair, pp)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, + receiver_decoder.write(address::Iface_AudioSource, pp)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, + receiver_decoder.write(address::Iface_AudioRepair, pp)); } TEST(receiver_decoder, activate_no_fec) { diff --git a/src/tests/roc_packet/test_concurrent_queue.cpp b/src/tests/roc_packet/test_concurrent_queue.cpp index d5ccb48c4a..14a9bb82e4 100644 --- a/src/tests/roc_packet/test_concurrent_queue.cpp +++ b/src/tests/roc_packet/test_concurrent_queue.cpp @@ -41,7 +41,7 @@ struct TestWriter : core::Thread { virtual void run() { core::sleep_for(core::ClockMonotonic, core::Microsecond * 10); - queue.write(packet); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(packet)); } }; @@ -54,7 +54,7 @@ TEST(concurrent_queue, blocking_write_one_read_one) { for (size_t i = 0; i < 100; i++) { PacketPtr wp = new_packet(); - queue.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp)); PacketPtr rp; UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(rp)); @@ -73,7 +73,7 @@ TEST(concurrent_queue, blocking_write_many_read_many) { } for (size_t j = 0; j < ROC_ARRAY_SIZE(packets); j++) { - queue.write(packets[j]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(packets[j])); } for (size_t j = 0; j < ROC_ARRAY_SIZE(packets); j++) { @@ -105,7 +105,7 @@ TEST(concurrent_queue, nonblocking_write_one_read_one) { for (size_t i = 0; i < 100; i++) { PacketPtr wp = new_packet(); - queue.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp)); PacketPtr rp; UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(rp)); @@ -124,7 +124,7 @@ TEST(concurrent_queue, nonblocking_write_many_read_many) { } for (size_t j = 0; j < ROC_ARRAY_SIZE(packets); j++) { - queue.write(packets[j]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(packets[j])); } for (size_t j = 0; j < ROC_ARRAY_SIZE(packets); j++) { @@ -140,7 +140,7 @@ TEST(concurrent_queue, nonblocking_read_empty) { for (size_t i = 0; i < 100; i++) { PacketPtr wp = new_packet(); - queue.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp)); PacketPtr rp; UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(rp)); diff --git a/src/tests/roc_packet/test_delayed_reader.cpp b/src/tests/roc_packet/test_delayed_reader.cpp index 1d002ee7a4..a5d5fc75a0 100644 --- a/src/tests/roc_packet/test_delayed_reader.cpp +++ b/src/tests/roc_packet/test_delayed_reader.cpp @@ -85,7 +85,7 @@ TEST(delayed_reader, no_delay) { for (seqnum_t n = 0; n < NumPackets; n++) { PacketPtr wp = new_packet(n); - queue.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp)); PacketPtr rp; UNSIGNED_LONGS_EQUAL(status::StatusOK, dr.read(rp)); @@ -105,7 +105,7 @@ TEST(delayed_reader, delay) { CHECK(!p); packets[n] = new_packet(n); - queue.write(packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(packets[n])); } for (seqnum_t n = 0; n < NumPackets; n++) { @@ -120,7 +120,7 @@ TEST(delayed_reader, delay) { for (seqnum_t n = 0; n < NumPackets; n++) { PacketPtr wp = new_packet(NumPackets + n); - queue.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp)); PacketPtr rp; UNSIGNED_LONGS_EQUAL(status::StatusOK, dr.read(rp)); @@ -139,7 +139,7 @@ TEST(delayed_reader, instant) { for (seqnum_t n = 0; n < NumPackets; n++) { packets[n] = new_packet(n); - queue.write(packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(packets[n])); } for (seqnum_t n = 0; n < NumPackets; n++) { @@ -161,7 +161,7 @@ TEST(delayed_reader, trim) { for (seqnum_t n = 0; n < NumPackets * 2; n++) { packets[n] = new_packet(n); - queue.write(packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(packets[n])); } for (seqnum_t n = NumPackets; n < NumPackets * 2; n++) { @@ -183,7 +183,7 @@ TEST(delayed_reader, late_duplicates) { for (seqnum_t n = 0; n < NumPackets; n++) { packets[n] = new_packet(n); - queue.write(packets[n]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(packets[n])); } for (seqnum_t n = 0; n < NumPackets; n++) { @@ -194,7 +194,7 @@ TEST(delayed_reader, late_duplicates) { for (seqnum_t n = 0; n < NumPackets; n++) { PacketPtr wp = new_packet(n); - queue.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp)); PacketPtr rp; UNSIGNED_LONGS_EQUAL(status::StatusOK, dr.read(rp)); diff --git a/src/tests/roc_packet/test_helpers/status_writer.h b/src/tests/roc_packet/test_helpers/status_writer.h new file mode 100644 index 0000000000..703b98fbcc --- /dev/null +++ b/src/tests/roc_packet/test_helpers/status_writer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef ROC_PACKET_TEST_HELPERS_STATUS_WRITER_H_ +#define ROC_PACKET_TEST_HELPERS_STATUS_WRITER_H_ + +#include "roc_core/noncopyable.h" +#include "roc_packet/iwriter.h" + +namespace roc { +namespace packet { +namespace test { + +class StatusWriter : public IWriter, public core::NonCopyable<> { +public: + explicit StatusWriter(status::StatusCode code) + : code_(code) { + } + + virtual ROC_ATTR_NODISCARD status::StatusCode write(const PacketPtr&) { + return code_; + } + +private: + status::StatusCode code_; +}; + +} // namespace test +} // namespace packet +} // namespace roc + +#endif // ROC_PACKET_TEST_HELPERS_STATUS_WRITER_H_ diff --git a/src/tests/roc_packet/test_interleaver.cpp b/src/tests/roc_packet/test_interleaver.cpp index 3878608aed..51a9d15232 100644 --- a/src/tests/roc_packet/test_interleaver.cpp +++ b/src/tests/roc_packet/test_interleaver.cpp @@ -13,6 +13,7 @@ #include "roc_packet/interleaver.h" #include "roc_packet/packet_factory.h" #include "roc_packet/queue.h" +#include "test_helpers/status_writer.h" namespace roc { namespace packet { @@ -63,7 +64,7 @@ TEST(interleaver, read_write) { // Push every packet to interleaver. for (size_t i = 0; i < num_packets; i++) { - intrlvr.write(packets[i]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, intrlvr.write(packets[i])); } // Interleaver must put all packets to its writer because we put pricesly @@ -104,7 +105,7 @@ TEST(interleaver, flush) { for (size_t n = 0; n < num_packets; n++) { PacketPtr wp = new_packet(seqnum_t(n)); - intrlvr.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, intrlvr.write(wp)); intrlvr.flush(); LONGS_EQUAL(1, queue.size()); @@ -115,5 +116,20 @@ TEST(interleaver, flush) { } } +TEST(interleaver, failed_to_write_packet) { + const status::StatusCode codes[] = { + status::StatusUnknown, + status::StatusNoData, + }; + + for (size_t n = 0; n < ROC_ARRAY_SIZE(codes); ++n) { + test::StatusWriter writer(codes[n]); + Interleaver intrlvr(writer, arena, 1); + + PacketPtr pp = new_packet(seqnum_t(1)); + UNSIGNED_LONGS_EQUAL(codes[n], intrlvr.write(pp)); + } +} + } // namespace packet } // namespace roc diff --git a/src/tests/roc_packet/test_packet_shipper.cpp b/src/tests/roc_packet/test_packet_shipper.cpp new file mode 100644 index 0000000000..88ff236b5b --- /dev/null +++ b/src/tests/roc_packet/test_packet_shipper.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2023 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "roc_core/buffer_factory.h" +#include "roc_core/heap_arena.h" +#include "roc_packet/packet_factory.h" +#include "roc_packet/queue.h" +#include "roc_packet/shipper.h" +#include "roc_rtp/headers.h" +#include "test_helpers/status_writer.h" + +namespace roc { +namespace packet { + +namespace { + +struct TestComposer : public IComposer, public core::NonCopyable<> { + TestComposer() + : compose_call_count(0) { + } + + virtual bool align(core::Slice&, size_t, size_t) { + return true; + } + + virtual bool prepare(Packet&, core::Slice&, size_t) { + return true; + } + + virtual bool pad(Packet&, size_t) { + return true; + } + + virtual bool compose(Packet&) { + ++compose_call_count; + return true; + } + + unsigned compose_call_count; +}; + +PacketPtr new_packet(PacketFactory& packet_factory, + core::BufferFactory& buffer_factory) { + PacketPtr packet = packet_factory.new_packet(); + CHECK(packet); + + packet->add_flags(Packet::FlagRTP); + packet->rtp()->payload_type = rtp::PayloadType_L16_Stereo; + + core::Slice buffer = buffer_factory.new_buffer(); + CHECK(buffer); + packet->rtp()->payload = buffer; + + return packet; +} + +enum { PacketSz = 128 }; + +core::HeapArena arena; +PacketFactory packet_factory(arena); +core::BufferFactory buffer_factory(arena, PacketSz); + +} // namespace + +TEST_GROUP(shipper) {}; + +TEST(shipper, verify_proxy_write_status_code_as_is) { + const status::StatusCode codes[] = { + status::StatusOK, + status::StatusUnknown, + status::StatusNoData, + }; + + for (size_t n = 0; n < ROC_ARRAY_SIZE(codes); ++n) { + address::SocketAddr addr; + TestComposer composer; + test::StatusWriter writer(codes[n]); + + Shipper shipper(addr, composer, writer); + + PacketPtr pp = new_packet(packet_factory, buffer_factory); + UNSIGNED_LONGS_EQUAL(codes[n], shipper.write(pp)); + } +} + +TEST(shipper, verify_flags_if_port_and_host_is_not_set) { + address::SocketAddr addr; + TestComposer composer; + Queue queue; + + Shipper shipper(addr, composer, queue); + + PacketPtr wp = new_packet(packet_factory, buffer_factory); + + CHECK((wp->flags() & Packet::FlagUDP) == 0); + CHECK(!wp->udp()); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, shipper.write(wp)); + + CHECK((wp->flags() & Packet::FlagUDP) == 0); + CHECK(!wp->udp()); + + packet::PacketPtr rp; + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(rp)); + CHECK(wp == rp); +} + +TEST(shipper, verify_flags_if_port_and_host_is_set) { + address::SocketAddr addr; + CHECK(addr.set_host_port_auto("127.0.0.1", 0)); + + TestComposer composer; + Queue queue; + + Shipper shipper(addr, composer, queue); + + PacketPtr wp = new_packet(packet_factory, buffer_factory); + + CHECK((wp->flags() & Packet::FlagUDP) == 0); + CHECK(!wp->udp()); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, shipper.write(wp)); + + CHECK(wp->flags() & Packet::FlagUDP); + CHECK(addr == wp->udp()->dst_addr); + + packet::PacketPtr rp; + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(rp)); + CHECK(wp == rp); +} + +TEST(shipper, verify_flags_if_packet_is_composed) { + address::SocketAddr addr; + TestComposer composer; + Queue queue; + + Shipper shipper(addr, composer, queue); + + PacketPtr wp = new_packet(packet_factory, buffer_factory); + wp->add_flags(Packet::FlagComposed); + + CHECK(wp->flags() & Packet::FlagComposed); + UNSIGNED_LONGS_EQUAL(0, composer.compose_call_count); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, shipper.write(wp)); + + CHECK(wp->flags() & Packet::FlagComposed); + UNSIGNED_LONGS_EQUAL(0, composer.compose_call_count); + + packet::PacketPtr rp; + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(rp)); + CHECK(wp == rp); +} + +TEST(shipper, verify_flags_if_packet_is_not_composed) { + address::SocketAddr addr; + TestComposer composer; + Queue queue; + + Shipper shipper(addr, composer, queue); + + PacketPtr wp = new_packet(packet_factory, buffer_factory); + + CHECK((wp->flags() & Packet::FlagComposed) == 0); + UNSIGNED_LONGS_EQUAL(0, composer.compose_call_count); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, shipper.write(wp)); + + UNSIGNED_LONGS_EQUAL(1, composer.compose_call_count); + CHECK(wp->flags() & Packet::FlagComposed); + + packet::PacketPtr rp; + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(rp)); + CHECK(wp == rp); +} + +} // namespace packet +} // namespace roc diff --git a/src/tests/roc_packet/test_router.cpp b/src/tests/roc_packet/test_router.cpp index 43ae802901..0fe5dba324 100644 --- a/src/tests/roc_packet/test_router.cpp +++ b/src/tests/roc_packet/test_router.cpp @@ -39,7 +39,7 @@ TEST(router, no_routes) { PacketPtr p = new_packet(0, Packet::FlagAudio); - router.write(p); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, router.write(p)); LONGS_EQUAL(1, p->getref()); } @@ -56,11 +56,11 @@ TEST(router, one_route) { PacketPtr pf1 = new_packet(0, Packet::FlagFEC); PacketPtr pf2 = new_packet(0, Packet::FlagFEC); - router.write(wpa1); - router.write(wpa2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, router.write(wpa1)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, router.write(wpa2)); - router.write(pf1); - router.write(pf2); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, router.write(pf1)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, router.write(pf2)); LONGS_EQUAL(2, wpa1->getref()); LONGS_EQUAL(2, wpa2->getref()); @@ -95,11 +95,11 @@ TEST(router, two_routes) { PacketPtr wpf1 = new_packet(0, Packet::FlagFEC); PacketPtr wpf2 = new_packet(0, Packet::FlagFEC); - router.write(wpa1); - router.write(wpa2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, router.write(wpa1)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, router.write(wpa2)); - router.write(wpf1); - router.write(wpf2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, router.write(wpf1)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, router.write(wpf2)); LONGS_EQUAL(2, wpa1->getref()); LONGS_EQUAL(2, wpa2->getref()); @@ -136,13 +136,16 @@ TEST(router, same_route_different_sources) { Queue queue; CHECK(router.add_route(queue, Packet::FlagAudio)); - router.write(new_packet(11, Packet::FlagAudio)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + router.write(new_packet(11, Packet::FlagAudio))); UNSIGNED_LONGS_EQUAL(1, queue.size()); - router.write(new_packet(22, Packet::FlagAudio)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, + router.write(new_packet(22, Packet::FlagAudio))); UNSIGNED_LONGS_EQUAL(1, queue.size()); - router.write(new_packet(11, Packet::FlagAudio)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + router.write(new_packet(11, Packet::FlagAudio))); UNSIGNED_LONGS_EQUAL(2, queue.size()); } @@ -155,8 +158,9 @@ TEST(router, different_routes_same_source) { Queue queue_f; CHECK(router.add_route(queue_f, Packet::FlagFEC)); - router.write(new_packet(11, Packet::FlagAudio)); - router.write(new_packet(11, Packet::FlagFEC)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + router.write(new_packet(11, Packet::FlagAudio))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, router.write(new_packet(11, Packet::FlagFEC))); UNSIGNED_LONGS_EQUAL(1, queue_a.size()); UNSIGNED_LONGS_EQUAL(1, queue_f.size()); @@ -171,8 +175,9 @@ TEST(router, different_routes_different_sources) { Queue queue_f; CHECK(router.add_route(queue_f, Packet::FlagFEC)); - router.write(new_packet(11, Packet::FlagAudio)); - router.write(new_packet(22, Packet::FlagFEC)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + router.write(new_packet(11, Packet::FlagAudio))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, router.write(new_packet(22, Packet::FlagFEC))); UNSIGNED_LONGS_EQUAL(1, queue_a.size()); UNSIGNED_LONGS_EQUAL(1, queue_f.size()); diff --git a/src/tests/roc_packet/test_sorted_queue.cpp b/src/tests/roc_packet/test_sorted_queue.cpp index c0bdb8d90f..a7e7b75193 100644 --- a/src/tests/roc_packet/test_sorted_queue.cpp +++ b/src/tests/roc_packet/test_sorted_queue.cpp @@ -54,8 +54,8 @@ TEST(sorted_queue, two_packets) { PacketPtr wp1 = new_packet(1); PacketPtr wp2 = new_packet(2); - queue.write(wp2); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); LONGS_EQUAL(2, queue.size()); @@ -99,7 +99,8 @@ TEST(sorted_queue, many_packets) { } for (ssize_t n = 0; n < NumPackets; n++) { - queue.write(packets[(n + NumPackets / 2) % NumPackets]); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(packets[(n + NumPackets / 2) % NumPackets])); } LONGS_EQUAL(NumPackets, queue.size()); @@ -122,7 +123,7 @@ TEST(sorted_queue, out_of_order) { PacketPtr wp1 = new_packet(1); PacketPtr wp2 = new_packet(2); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); LONGS_EQUAL(1, queue.size()); @@ -135,7 +136,7 @@ TEST(sorted_queue, out_of_order) { LONGS_EQUAL(0, queue.size()); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); LONGS_EQUAL(1, queue.size()); @@ -160,11 +161,11 @@ TEST(sorted_queue, out_of_order_many_packets) { SortedQueue queue(0); for (packet::seqnum_t n = 0; n < 7; ++n) { - queue.write(new_packet(n)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(new_packet(n))); } for (packet::seqnum_t n = 11; n < NumPackets; ++n) { - queue.write(new_packet(n)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(new_packet(n))); } for (packet::seqnum_t n = 0; n < 7; ++n) { @@ -175,8 +176,8 @@ TEST(sorted_queue, out_of_order_many_packets) { CHECK(p->rtp()->seqnum == n); } - queue.write(new_packet(9)); - queue.write(new_packet(10)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(new_packet(9))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(new_packet(10))); for (packet::seqnum_t n = 9; n < NumPackets; ++n) { packet::PacketPtr p; @@ -185,8 +186,8 @@ TEST(sorted_queue, out_of_order_many_packets) { CHECK(p->rtp()->seqnum == n); if (n == 10) { - queue.write(new_packet(8)); - queue.write(new_packet(7)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(new_packet(8))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(new_packet(7))); UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(p)); UNSIGNED_LONGS_EQUAL(7, p->rtp()->seqnum); @@ -203,8 +204,8 @@ TEST(sorted_queue, one_duplicate) { PacketPtr wp1 = new_packet(1); PacketPtr wp2 = new_packet(1); - queue.write(wp1); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, queue.write(wp2)); LONGS_EQUAL(1, queue.size()); @@ -231,13 +232,13 @@ TEST(sorted_queue, many_duplicates) { SortedQueue queue(0); for (seqnum_t n = 0; n < NumPackets; n++) { - queue.write(new_packet(n)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(new_packet(n))); } LONGS_EQUAL(NumPackets, queue.size()); for (seqnum_t n = 0; n < NumPackets; n++) { - queue.write(new_packet(n)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, queue.write(new_packet(n))); } LONGS_EQUAL(NumPackets, queue.size()); @@ -258,9 +259,9 @@ TEST(sorted_queue, max_size) { PacketPtr wp2 = new_packet(2); PacketPtr wp3 = new_packet(3); - queue.write(wp1); - queue.write(wp2); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); + UNSIGNED_LONGS_EQUAL(status::StatusNoData, queue.write(wp3)); LONGS_EQUAL(2, queue.size()); @@ -273,7 +274,7 @@ TEST(sorted_queue, max_size) { LONGS_EQUAL(1, queue.size()); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); LONGS_EQUAL(2, queue.size()); @@ -290,9 +291,9 @@ TEST(sorted_queue, overflow_ordered1) { PacketPtr wp2 = new_packet(sn); PacketPtr wp3 = new_packet(seqnum_t(sn + 10)); - queue.write(wp1); - queue.write(wp2); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); LONGS_EQUAL(3, queue.size()); @@ -322,9 +323,9 @@ TEST(sorted_queue, overflow_ordered2) { PacketPtr wp2 = new_packet(sn); PacketPtr wp3 = new_packet(seqnum_t(sn + 10)); - queue.write(wp1); - queue.write(wp2); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); LONGS_EQUAL(3, queue.size()); @@ -354,9 +355,9 @@ TEST(sorted_queue, overflow_sorting) { PacketPtr wp2 = new_packet(sn); PacketPtr wp3 = new_packet(seqnum_t(sn + 10)); - queue.write(wp2); - queue.write(wp1); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); LONGS_EQUAL(3, queue.size()); @@ -386,7 +387,7 @@ TEST(sorted_queue, overflow_out_of_order) { PacketPtr wp2 = new_packet(sn); PacketPtr wp3 = new_packet(sn / 2); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); LONGS_EQUAL(1, queue.size()); PacketPtr rp1; @@ -394,7 +395,7 @@ TEST(sorted_queue, overflow_out_of_order) { CHECK(wp1 == rp1); LONGS_EQUAL(0, queue.size()); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); LONGS_EQUAL(1, queue.size()); PacketPtr rp2; @@ -402,7 +403,7 @@ TEST(sorted_queue, overflow_out_of_order) { CHECK(wp2 == rp2); LONGS_EQUAL(0, queue.size()); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); LONGS_EQUAL(1, queue.size()); PacketPtr rp3; @@ -426,15 +427,15 @@ TEST(sorted_queue, latest) { LONGS_EQUAL(0, queue.size()); CHECK(!queue.latest()); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); LONGS_EQUAL(1, queue.size()); CHECK(queue.latest() == wp1); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); LONGS_EQUAL(2, queue.size()); CHECK(queue.latest() == wp2); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); LONGS_EQUAL(3, queue.size()); CHECK(queue.latest() == wp2); @@ -465,7 +466,7 @@ TEST(sorted_queue, latest) { LONGS_EQUAL(0, queue.size()); CHECK(queue.latest() == wp2); - queue.write(wp4); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp4)); LONGS_EQUAL(1, queue.size()); CHECK(queue.latest() == wp4); } diff --git a/src/tests/roc_pipeline/test_helpers/control_writer.h b/src/tests/roc_pipeline/test_helpers/control_writer.h index aebf47fcf0..46fba90281 100644 --- a/src/tests/roc_pipeline/test_helpers/control_writer.h +++ b/src/tests/roc_pipeline/test_helpers/control_writer.h @@ -56,7 +56,7 @@ class ControlWriter : public core::NonCopyable<> { bld.begin_sr(sr); bld.end_sr(); - writer_.write(new_packet_(buff)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer_.write(new_packet_(buff))); } void set_source(packet::stream_source_t source) { diff --git a/src/tests/roc_pipeline/test_helpers/noop_arena.h b/src/tests/roc_pipeline/test_helpers/noop_arena.h new file mode 100644 index 0000000000..fd568b1b1a --- /dev/null +++ b/src/tests/roc_pipeline/test_helpers/noop_arena.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef ROC_PIPELINE_TEST_HELPERS_NOOP_ARENA_H_ +#define ROC_PIPELINE_TEST_HELPERS_NOOP_ARENA_H_ + +#include "roc_core/iarena.h" +#include "roc_core/noncopyable.h" + +namespace roc { +namespace pipeline { +namespace test { + +struct NoopArena : public core::IArena, public core::NonCopyable<> { + virtual void* allocate(size_t) { + return NULL; + } + + virtual void deallocate(void*) { + } +}; + +} // namespace test +} // namespace pipeline +} // namespace roc + +#endif // ROC_PIPELINE_TEST_HELPERS_NOOP_ARENA_H_ diff --git a/src/tests/roc_pipeline/test_helpers/packet_sender.h b/src/tests/roc_pipeline/test_helpers/packet_sender.h index 614ed26ed1..c2152a7545 100644 --- a/src/tests/roc_pipeline/test_helpers/packet_sender.h +++ b/src/tests/roc_pipeline/test_helpers/packet_sender.h @@ -36,8 +36,8 @@ class PacketSender : public packet::IWriter, core::NonCopyable<> { , n_control_(0) { } - virtual void write(const packet::PacketPtr& pp) { - queue_.write(pp); + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr& pp) { + return queue_.write(pp); } size_t n_source() const { @@ -63,15 +63,18 @@ class PacketSender : public packet::IWriter, core::NonCopyable<> { if (pp->flags() & packet::Packet::FlagControl) { CHECK(control_writer_); - control_writer_->write(copy_packet_(pp)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + control_writer_->write(copy_packet_(pp))); n_control_++; } else if (pp->flags() & packet::Packet::FlagRepair) { CHECK(repair_writer_); - repair_writer_->write(copy_packet_(pp)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + repair_writer_->write(copy_packet_(pp))); n_repair_++; } else { CHECK(source_writer_); - source_writer_->write(copy_packet_(pp)); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + source_writer_->write(copy_packet_(pp))); n_source_++; np++; } diff --git a/src/tests/roc_pipeline/test_helpers/packet_writer.h b/src/tests/roc_pipeline/test_helpers/packet_writer.h index eda6545c27..65385059ac 100644 --- a/src/tests/roc_pipeline/test_helpers/packet_writer.h +++ b/src/tests/roc_pipeline/test_helpers/packet_writer.h @@ -59,7 +59,9 @@ class PacketWriter : public core::NonCopyable<> { CHECK(num_packets > 0); for (size_t np = 0; np < num_packets; np++) { - writer_.write(new_packet_(samples_per_packet, sample_spec)); + UNSIGNED_LONGS_EQUAL( + status::StatusOK, + writer_.write(new_packet_(samples_per_packet, sample_spec))); } } diff --git a/src/tests/roc_pipeline/test_receiver_endpoint.cpp b/src/tests/roc_pipeline/test_receiver_endpoint.cpp new file mode 100644 index 0000000000..c798b81c00 --- /dev/null +++ b/src/tests/roc_pipeline/test_receiver_endpoint.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2023 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "roc_address/protocol.h" +#include "roc_audio/mixer.h" +#include "roc_audio/sample.h" +#include "roc_core/heap_arena.h" +#include "roc_packet/packet_factory.h" +#include "roc_packet/queue.h" +#include "roc_pipeline/receiver_endpoint.h" +#include "roc_pipeline/receiver_session_group.h" +#include "roc_pipeline/receiver_state.h" +#include "roc_status/status_code.h" +#include "test_helpers/noop_arena.h" + +namespace roc { +namespace pipeline { + +namespace { + +class StatusWriter : public packet::IWriter, public core::NonCopyable<> { +public: + explicit StatusWriter(status::StatusCode code) + : code_(code) { + } + + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr&) { + return code_; + } + +private: + status::StatusCode code_; +}; + +void check_no_memory(bool is_valid, + const address::Protocol* protos, + unsigned protos_count, + packet::PacketFactory& packet_factory, + core::BufferFactory& buffer_factory, + core::BufferFactory& sample_factory) { + test::NoopArena noop_arena; + + for (unsigned n = 0; n < protos_count; ++n) { + rtp::FormatMap fmt_map(noop_arena); + audio::Mixer mixer(sample_factory, false); + + ReceiverState receiver_state; + ReceiverConfig receiver_config; + ReceiverSessionGroup session_group(receiver_config, receiver_state, mixer, + fmt_map, packet_factory, buffer_factory, + sample_factory, noop_arena); + + ReceiverEndpoint endpoint(protos[n], receiver_state, session_group, fmt_map, + noop_arena); + + CHECK(is_valid == endpoint.is_valid()); + } +} + +enum { PacketSz = 512 }; + +const uint8_t Ref_rtp[] = { + /* RTP header */ + 0x80, 0x0B, 0x55, 0x66, // + 0x77, 0x88, 0x99, 0xaa, // + 0x11, 0x22, 0x33, 0x44, // + /* Payload */ + 0x01, 0x02, 0x03, 0x04, // + 0x05, 0x06, 0x07, 0x08, // + 0x09, 0x0a +}; + +core::HeapArena arena; +packet::PacketFactory packet_factory(arena); +core::BufferFactory buffer_factory(arena, PacketSz); +core::BufferFactory sample_factory(arena, PacketSz); + +} // namespace + +TEST_GROUP(receiver_endpoint) {}; + +TEST(receiver_endpoint, valid) { + rtp::FormatMap fmt_map(arena); + audio::Mixer mixer(sample_factory, false); + + ReceiverState receiver_state; + ReceiverConfig receiver_config; + ReceiverSessionGroup session_group(receiver_config, receiver_state, mixer, fmt_map, + packet_factory, buffer_factory, sample_factory, + arena); + + ReceiverEndpoint endpoint(address::Proto_RTP, receiver_state, session_group, fmt_map, + arena); + CHECK(endpoint.is_valid()); +} + +TEST(receiver_endpoint, is_valid_unknown_proto) { + rtp::FormatMap fmt_map(arena); + audio::Mixer mixer(sample_factory, false); + + ReceiverState receiver_state; + ReceiverConfig receiver_config; + ReceiverSessionGroup session_group(receiver_config, receiver_state, mixer, fmt_map, + packet_factory, buffer_factory, sample_factory, + arena); + + ReceiverEndpoint endpoint(address::Proto_None, receiver_state, session_group, fmt_map, + arena); + CHECK(!endpoint.is_valid()); +} + +TEST(receiver_endpoint, is_valid_no_memory) { + const address::Protocol protos_require_memory[] = { + address::Proto_RTP_LDPC_Source, + address::Proto_RTP_RS8M_Source, + address::Proto_RS8M_Repair, + address::Proto_LDPC_Repair, + }; + + const address::Protocol protos_do_not_require_memory[] = { + address::Proto_RTP, + address::Proto_RTCP, + }; + + check_no_memory(false, protos_require_memory, ROC_ARRAY_SIZE(protos_require_memory), + packet_factory, buffer_factory, sample_factory); + + check_no_memory(true, protos_do_not_require_memory, + ROC_ARRAY_SIZE(protos_do_not_require_memory), packet_factory, + buffer_factory, sample_factory); +} + +TEST(receiver_endpoint, write_read_packet) { + rtp::FormatMap fmt_map(arena); + audio::Mixer mixer(sample_factory, false); + + ReceiverState receiver_state; + ReceiverConfig receiver_config; + ReceiverSessionGroup session_group(receiver_config, receiver_state, mixer, fmt_map, + packet_factory, buffer_factory, sample_factory, + arena); + + ReceiverEndpoint endpoint(address::Proto_RTP, receiver_state, session_group, fmt_map, + arena); + CHECK(endpoint.is_valid()); + CHECK(!receiver_state.has_pending_packets()); + + packet::PacketPtr pp = packet_factory.new_packet(); + CHECK(pp); + + core::Slice buffer = buffer_factory.new_buffer(); + CHECK(buffer); + + buffer.reslice(0, sizeof(Ref_rtp)); + for (size_t i = 0; i < sizeof(Ref_rtp); i++) { + buffer.data()[i] = Ref_rtp[i]; + } + + pp->set_data(buffer); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, endpoint.writer().write(pp)); + CHECK(receiver_state.has_pending_packets()); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, endpoint.pull_packets()); + CHECK(!receiver_state.has_pending_packets()); +} + +TEST(receiver_endpoint, pull_packets_no_data) { + rtp::FormatMap fmt_map(arena); + StatusWriter writer(status::StatusNoData); + ReceiverState receiver_state; + + ReceiverEndpoint endpoint(address::Proto_RTP, receiver_state, writer, fmt_map, arena); + CHECK(endpoint.is_valid()); + CHECK(!receiver_state.has_pending_packets()); + + packet::PacketPtr pp = packet_factory.new_packet(); + CHECK(pp); + + core::Slice buffer = buffer_factory.new_buffer(); + CHECK(buffer); + + buffer.reslice(0, sizeof(Ref_rtp)); + for (size_t i = 0; i < sizeof(Ref_rtp); i++) { + buffer.data()[i] = Ref_rtp[i]; + } + + pp->set_data(buffer); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, endpoint.writer().write(pp)); + CHECK(receiver_state.has_pending_packets()); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, endpoint.pull_packets()); + CHECK(!receiver_state.has_pending_packets()); +} + +TEST(receiver_endpoint, pull_packets_failed) { + rtp::FormatMap fmt_map(arena); + StatusWriter writer(status::StatusUnknown); + ReceiverState receiver_state; + + ReceiverEndpoint endpoint(address::Proto_RTP, receiver_state, writer, fmt_map, arena); + CHECK(endpoint.is_valid()); + CHECK(!receiver_state.has_pending_packets()); + + packet::PacketPtr pp = packet_factory.new_packet(); + CHECK(pp); + + core::Slice buffer = buffer_factory.new_buffer(); + CHECK(buffer); + + buffer.reslice(0, sizeof(Ref_rtp)); + for (size_t i = 0; i < sizeof(Ref_rtp); i++) { + buffer.data()[i] = Ref_rtp[i]; + } + + pp->set_data(buffer); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, endpoint.writer().write(pp)); + CHECK(receiver_state.has_pending_packets()); + + UNSIGNED_LONGS_EQUAL(status::StatusUnknown, endpoint.pull_packets()); + CHECK(!receiver_state.has_pending_packets()); +} + +} // namespace pipeline +} // namespace roc diff --git a/src/tests/roc_pipeline/test_sender_endpoint.cpp b/src/tests/roc_pipeline/test_sender_endpoint.cpp new file mode 100644 index 0000000000..acf55db2c1 --- /dev/null +++ b/src/tests/roc_pipeline/test_sender_endpoint.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "roc_address/protocol.h" +#include "roc_core/heap_arena.h" +#include "roc_packet/packet_factory.h" +#include "roc_packet/queue.h" +#include "roc_pipeline/sender_endpoint.h" +#include "roc_status/status_code.h" +#include "test_helpers/noop_arena.h" + +namespace roc { +namespace pipeline { + +TEST_GROUP(sender_endpoint) {}; + +TEST(sender_endpoint, valid) { + address::SocketAddr addr; + packet::Queue queue; + core::HeapArena arena; + + SenderEndpoint endpoint(address::Proto_RTP, addr, queue, arena); + CHECK(endpoint.is_valid()); +} + +TEST(sender_endpoint, is_valid_unknown_proto) { + address::SocketAddr addr; + packet::Queue queue; + core::HeapArena arena; + + SenderEndpoint endpoint(address::Proto_None, addr, queue, arena); + CHECK(!endpoint.is_valid()); +} + +TEST(sender_endpoint, is_valid_no_memory) { + const address::Protocol protos[] = { + address::Proto_RTP, + address::Proto_RTCP, + address::Proto_RTP_LDPC_Source, + address::Proto_RTP_RS8M_Source, + address::Proto_RS8M_Repair, + address::Proto_LDPC_Repair, + }; + + test::NoopArena noop_arena; + + for (unsigned n = 0; n < ROC_ARRAY_SIZE(protos); ++n) { + address::SocketAddr addr; + packet::Queue queue; + + SenderEndpoint endpoint(protos[n], addr, queue, noop_arena); + CHECK(!endpoint.is_valid()); + } +} + +TEST(sender_endpoint, write_read_packet) { + address::SocketAddr addr; + packet::Queue queue; + core::HeapArena arena; + + SenderEndpoint endpoint(address::Proto_RTP, addr, queue, arena); + CHECK(endpoint.is_valid()); + + packet::PacketFactory packet_factory(arena); + packet::PacketPtr wp = packet_factory.new_packet(); + CHECK(wp); + wp->add_flags(packet::Packet::FlagComposed); + + UNSIGNED_LONGS_EQUAL(status::StatusOK, endpoint.writer().write(wp)); + + packet::PacketPtr rp; + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(rp)); + CHECK(wp == rp); +} + +} // namespace pipeline +} // namespace roc diff --git a/src/tests/roc_pipeline/test_sender_sink_receiver_source.cpp b/src/tests/roc_pipeline/test_sender_sink_receiver_source.cpp index 6af0dd5891..e0e3108c2b 100644 --- a/src/tests/roc_pipeline/test_sender_sink_receiver_source.cpp +++ b/src/tests/roc_pipeline/test_sender_sink_receiver_source.cpp @@ -203,7 +203,7 @@ void filter_packets(int flags, packet::IReader& reader, packet::IWriter& writer) } } - writer.write(pp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, writer.write(pp)); } } diff --git a/src/tests/roc_rtcp/test_session.cpp b/src/tests/roc_rtcp/test_session.cpp new file mode 100644 index 0000000000..09239011cd --- /dev/null +++ b/src/tests/roc_rtcp/test_session.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2023 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "roc_core/buffer_factory.h" +#include "roc_core/heap_arena.h" +#include "roc_core/noncopyable.h" +#include "roc_core/time.h" +#include "roc_packet/iwriter.h" +#include "roc_packet/packet_factory.h" +#include "roc_packet/queue.h" +#include "roc_rtcp/composer.h" +#include "roc_rtcp/headers.h" +#include "roc_rtcp/ireceiver_hooks.h" +#include "roc_rtcp/isender_hooks.h" +#include "roc_rtcp/session.h" +#include "roc_status/status_code.h" + +namespace roc { +namespace rtcp { + +namespace { + +class StatusWriter : public packet::IWriter, public core::NonCopyable<> { +public: + explicit StatusWriter(status::StatusCode code) + : call_count(0) + , code_(code) { + } + + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr&) { + ++call_count; + return code_; + } + + unsigned call_count; + +private: + status::StatusCode code_; +}; + +struct TestReceiverHooks : public IReceiverHooks, public core::NonCopyable<> { + virtual void on_update_source(packet::stream_source_t, const char*) { + } + + virtual void on_remove_source(packet::stream_source_t) { + } + + virtual size_t on_get_num_sources() { + return 0; + } + + virtual ReceptionMetrics on_get_reception_metrics(size_t) { + ReceptionMetrics metrics; + return metrics; + } + + virtual void on_add_sending_metrics(const SendingMetrics& metrics) { + sending_metrics = metrics; + } + + virtual void on_add_link_metrics(const LinkMetrics&) { + } + + SendingMetrics sending_metrics; +}; + +struct TestSenderHooks : public ISenderHooks, public core::NonCopyable<> { + virtual size_t on_get_num_sources() { + return 0; + } + + virtual packet::stream_source_t on_get_sending_source(size_t) { + return packet::stream_source_t(0); + } + + virtual SendingMetrics on_get_sending_metrics(core::nanoseconds_t report_time) { + SendingMetrics metrics; + metrics.origin_time = report_time; + + return metrics; + } + + virtual void on_add_reception_metrics(const ReceptionMetrics&) { + } + + virtual void on_add_link_metrics(const LinkMetrics&) { + } +}; + +} // namespace + +TEST_GROUP(session) {}; + +TEST(session, write_packet) { + enum { PacketSz = 128 }; + + TestReceiverHooks receiver_hooks; + TestSenderHooks sender_hooks; + Composer composer; + packet::Queue queue; + + core::HeapArena arena; + packet::PacketFactory packet_factory(arena); + core::BufferFactory buffer_factory(arena, PacketSz); + + Session session(&receiver_hooks, &sender_hooks, &queue, composer, packet_factory, + buffer_factory); + CHECK(session.is_valid()); + + const core::nanoseconds_t now = core::Second; + UNSIGNED_LONGS_EQUAL(status::StatusOK, session.generate_packets(now)); + + packet::PacketPtr pp; + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.read(pp)); + CHECK(pp); + + UNSIGNED_LONGS_EQUAL(0, receiver_hooks.sending_metrics.origin_time); + UNSIGNED_LONGS_EQUAL(status::StatusOK, session.write(pp)); + UNSIGNED_LONGS_EQUAL(now, receiver_hooks.sending_metrics.origin_time); +} + +TEST(session, failed_to_write_packet) { + enum { PacketSz = 1 }; + CHECK(PacketSz < sizeof(header::PacketHeader)); + + TestReceiverHooks receiver_hooks; + TestSenderHooks sender_hooks; + Composer composer; + StatusWriter writer(status::StatusOK); + + core::HeapArena arena; + packet::PacketFactory packet_factory(arena); + core::BufferFactory buffer_factory(arena, PacketSz); + + Session session(&receiver_hooks, &sender_hooks, &writer, composer, packet_factory, + buffer_factory); + CHECK(session.is_valid()); + + packet::PacketPtr pp = packet_factory.new_packet(); + pp->add_flags(packet::Packet::FlagRTCP); + + core::Slice buf = buffer_factory.new_buffer(); + pp->rtcp()->data = buf; + + UNSIGNED_LONGS_EQUAL(status::StatusNoData, session.write(pp)); +} + +TEST(session, generate_packets_failed_to_write) { + enum { PacketSz = 128 }; + + TestReceiverHooks receiver_hooks; + TestSenderHooks sender_hooks; + Composer composer; + StatusWriter writer(status::StatusUnknown); + + core::HeapArena arena; + packet::PacketFactory packet_factory(arena); + core::BufferFactory buffer_factory(arena, PacketSz); + + Session session(&receiver_hooks, &sender_hooks, &writer, composer, packet_factory, + buffer_factory); + CHECK(session.is_valid()); + + core::nanoseconds_t now = core::Second; + + UNSIGNED_LONGS_EQUAL(status::StatusUnknown, session.generate_packets(now)); + UNSIGNED_LONGS_EQUAL(1, writer.call_count); + + UNSIGNED_LONGS_EQUAL(status::StatusNoData, session.generate_packets(now)); + UNSIGNED_LONGS_EQUAL(1, writer.call_count); + + now += core::Second; + + UNSIGNED_LONGS_EQUAL(status::StatusUnknown, session.generate_packets(now)); + UNSIGNED_LONGS_EQUAL(2, writer.call_count); +} + +} // namespace rtcp +} // namespace roc diff --git a/src/tests/roc_rtp/test_populator.cpp b/src/tests/roc_rtp/test_populator.cpp index 2a60506588..ba829fd0c5 100644 --- a/src/tests/roc_rtp/test_populator.cpp +++ b/src/tests/roc_rtp/test_populator.cpp @@ -81,7 +81,7 @@ TEST(populator, empty_duration) { const packet::stream_timestamp_t expected_duration = 32; packet::PacketPtr wp = new_packet(packet_duration); - queue.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp)); packet::PacketPtr rp; LONGS_EQUAL(0, populator.read(rp)); @@ -101,7 +101,7 @@ TEST(populator, non_empty_duration) { core::Slice buffer = buffer_factory.new_buffer(); CHECK(buffer); packet::PacketPtr wp = new_packet(duration); - queue.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp)); packet::PacketPtr rp; LONGS_EQUAL(0, populator.read(rp)); diff --git a/src/tests/roc_rtp/test_timestamp_extractor.cpp b/src/tests/roc_rtp/test_timestamp_extractor.cpp index 0c102606fe..5e327253c1 100644 --- a/src/tests/roc_rtp/test_timestamp_extractor.cpp +++ b/src/tests/roc_rtp/test_timestamp_extractor.cpp @@ -26,6 +26,20 @@ namespace rtp { namespace { +class StatusWriter : public packet::IWriter, public core::NonCopyable<> { +public: + explicit StatusWriter(status::StatusCode code) + : code_(code) { + } + + virtual ROC_ATTR_NODISCARD status::StatusCode write(const packet::PacketPtr&) { + return code_; + } + +private: + status::StatusCode code_; +}; + core::HeapArena arena; static packet::PacketFactory packet_factory(arena); @@ -62,7 +76,7 @@ TEST(timestamp_extractor, single_write) { // write packet packet::PacketPtr wp = new_packet(555, rts, cts); - extractor.write(wp); + UNSIGNED_LONGS_EQUAL(status::StatusOK, extractor.write(wp)); // ensure packet was passed to inner writer CHECK_EQUAL(1, queue.size()); @@ -83,5 +97,24 @@ TEST(timestamp_extractor, single_write) { CHECK_EQUAL(rts - 1000, extractor.get_mapping(cts - core::Second)); } +TEST(timestamp_extractor, failed_to_write_packet) { + // 1 second = 1000 samples + const audio::SampleSpec sample_spec = + audio::SampleSpec(1000, audio::ChanLayout_Surround, 0x1); + + const status::StatusCode codes[] = { + status::StatusUnknown, + status::StatusNoData, + }; + + for (size_t n = 0; n < ROC_ARRAY_SIZE(codes); ++n) { + StatusWriter writer(codes[n]); + TimestampExtractor extractor(writer, sample_spec); + + packet::PacketPtr pp = new_packet(555, 0, 0); + UNSIGNED_LONGS_EQUAL(codes[n], extractor.write(pp)); + } +} + } // namespace rtp } // namespace roc diff --git a/src/tests/roc_rtp/test_timestamp_injector.cpp b/src/tests/roc_rtp/test_timestamp_injector.cpp index 36a416b8e8..b2f85ee5e4 100644 --- a/src/tests/roc_rtp/test_timestamp_injector.cpp +++ b/src/tests/roc_rtp/test_timestamp_injector.cpp @@ -100,9 +100,10 @@ TEST(timestamp_injector, negative_and_positive_dn) { LONGS_EQUAL(0, queue.size()); for (size_t i = 0; i < NPackets; i++) { - queue.write( - new_packet((packet::seqnum_t)i, - (packet::stream_timestamp_t)(packet_rtp_ts + i * PacketSz))); + UNSIGNED_LONGS_EQUAL(status::StatusOK, + queue.write(new_packet((packet::seqnum_t)i, + (packet::stream_timestamp_t)( + packet_rtp_ts + i * PacketSz)))); } LONGS_EQUAL(NPackets, queue.size()); diff --git a/src/tests/roc_rtp/test_validator.cpp b/src/tests/roc_rtp/test_validator.cpp index be131bda42..5852724763 100644 --- a/src/tests/roc_rtp/test_validator.cpp +++ b/src/tests/roc_rtp/test_validator.cpp @@ -84,14 +84,14 @@ TEST(validator, normal) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 1, 1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, 2, 2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp2)); @@ -107,14 +107,14 @@ TEST(validator, payload_id_jump) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 1, 1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt2, Src1, 2, 2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp2)); @@ -130,14 +130,14 @@ TEST(validator, source_id_jump) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 1, 1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src2, 2, 2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp2)); @@ -161,14 +161,14 @@ TEST(validator, seqnum_no_jump) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, sn1, 1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, sn2, 2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp2)); @@ -193,14 +193,14 @@ TEST(validator, seqnum_jump_up) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, sn1, 1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, sn2, 2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp2)); @@ -225,14 +225,14 @@ TEST(validator, seqnum_jump_down) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, sn2, 1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, sn1, 2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp2)); @@ -253,21 +253,21 @@ TEST(validator, seqnum_late) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, sn1, 1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, sn2, 2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp2)); CHECK(wp2 == rp2); packet::PacketPtr wp3 = new_packet(Pt1, Src1, sn3, 3, 0); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); packet::PacketPtr rp3; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp3)); @@ -291,14 +291,14 @@ TEST(validator, timestamp_no_jump) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 1, ts1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, 2, ts2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp2)); @@ -323,14 +323,14 @@ TEST(validator, timestamp_jump_up) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 1, ts1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, 2, ts2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp2)); @@ -355,14 +355,14 @@ TEST(validator, timestamp_jump_down) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 1, ts2, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, 2, ts1, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp2)); @@ -383,21 +383,21 @@ TEST(validator, timestamp_late) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 2, ts1, 0); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, 1, ts2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp2)); CHECK(wp2 == rp2); packet::PacketPtr wp3 = new_packet(Pt1, Src1, 3, ts3, 0); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); packet::PacketPtr rp3; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp3)); @@ -413,28 +413,28 @@ TEST(validator, cts_positive) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 1, 1, 100); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, 2, 2, 50); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp2)); CHECK(wp2 == rp2); packet::PacketPtr wp3 = new_packet(Pt1, Src1, 3, 3, 200); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); packet::PacketPtr rp3; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp3)); CHECK(wp3 == rp3); packet::PacketPtr wp4 = new_packet(Pt1, Src1, 4, 4, 150); - queue.write(wp4); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp4)); packet::PacketPtr rp4; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp4)); @@ -450,28 +450,28 @@ TEST(validator, cts_negative) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 1, 1, 100); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, 2, 2, -100); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp2)); CHECK(!rp2); packet::PacketPtr wp3 = new_packet(Pt1, Src1, 3, 3, 200); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); packet::PacketPtr rp3; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp3)); CHECK(wp3 == rp3); packet::PacketPtr wp4 = new_packet(Pt1, Src1, 4, 4, -200); - queue.write(wp4); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp4)); packet::PacketPtr rp4; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp4)); @@ -487,28 +487,28 @@ TEST(validator, cts_zero) { Validator validator(queue, config, SampleSpecs); packet::PacketPtr wp1 = new_packet(Pt1, Src1, 1, 1, 100); - queue.write(wp1); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp1)); packet::PacketPtr rp1; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp1)); CHECK(wp1 == rp1); packet::PacketPtr wp2 = new_packet(Pt1, Src1, 2, 2, 0); - queue.write(wp2); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp2)); packet::PacketPtr rp2; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp2)); CHECK(!rp2); packet::PacketPtr wp3 = new_packet(Pt1, Src1, 3, 3, 200); - queue.write(wp3); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp3)); packet::PacketPtr rp3; UNSIGNED_LONGS_EQUAL(status::StatusOK, validator.read(rp3)); CHECK(wp3 == rp3); packet::PacketPtr wp4 = new_packet(Pt1, Src1, 4, 4, 0); - queue.write(wp4); + UNSIGNED_LONGS_EQUAL(status::StatusOK, queue.write(wp4)); packet::PacketPtr rp4; UNSIGNED_LONGS_EQUAL(status::StatusNoData, validator.read(rp4));