common: Rename pkt_dispatch to reception_flow

The dispatching is what technique the class uses, but it does not
describe its responsibilities at all making it very hard to figure out
what role it plays in the architecture just by looking at the name.

Also removed all references to obsolete System call dispatcher
(different concept) in all the comments.
This commit is contained in:
Joni Räsänen 2022-03-03 08:57:49 +02:00
parent 97c235bb97
commit cce653b9b7
11 changed files with 117 additions and 130 deletions

View File

@ -34,7 +34,7 @@ target_sources(${PROJECT_NAME} PRIVATE
src/media_stream.cc
src/mingw_inet.cc
src/multicast.cc
src/pkt_dispatch.cc
src/reception_flow.cc
src/poll.cc
src/queue.cc
src/random.cc
@ -78,7 +78,7 @@ target_sources(${PROJECT_NAME} PRIVATE
src/hostname.hh
src/mingw_inet.hh
src/multicast.hh
src/pkt_dispatch.hh
src/reception_flow.hh
src/poll.hh
src/rtp.hh
src/zrtp.hh

View File

@ -23,7 +23,7 @@ namespace uvgrtp {
class srtp;
class srtcp;
class pkt_dispatcher;
class reception_flow;
class holepuncher;
class socket;
@ -238,9 +238,7 @@ namespace uvgrtp {
rtp_error_t install_receive_hook(void *arg, void (*hook)(void *, uvgrtp::frame::rtp_frame *));
/// \cond DO_NOT_DOCUMENT
/* If system call dispatcher is enabled and calling application has special requirements
* for the deallocation of a frame, it may install a deallocation hook which is called
* when SCD has processed the frame
/*
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if "hook" is nullptr */
@ -329,7 +327,7 @@ namespace uvgrtp {
rtp_format_t fmt_;
int flags_;
/* Media context config (SCD etc.) */
/* Media context config */
rtp_ctx_conf_t ctx_config_;
/* Media config f.ex. for Opus */
@ -338,12 +336,12 @@ namespace uvgrtp {
/* Has the media stream been initialized */
bool initialized_;
/* Primary handler keys for the RTP packet dispatcher */
/* Primary handler keys for the RTP reception flow */
uint32_t rtp_handler_key_;
uint32_t zrtp_handler_key_;
/* RTP packet dispatcher for the receiver */
uvgrtp::pkt_dispatcher *pkt_dispatcher_;
/* RTP packet reception flow */
uvgrtp::reception_flow *reception_flow_;
/* Media object associated with this media stream. */
uvgrtp::formats::media *media_;

View File

@ -118,7 +118,7 @@ typedef enum RTP_FLAGS {
enum RTP_CTX_ENABLE_FLAGS {
RCE_NO_FLAGS = 0 << 0,
/* Enable system call dispatcher (HEVC only) */
/* Obsolete */
RCE_SYSTEM_CALL_DISPATCHER = 1 << 2,
/** Use SRTP for this connection */

View File

@ -340,9 +340,8 @@ rtp_error_t uvgrtp::formats::h26x::push_nal_unit(uint8_t *data, size_t data_len,
size_t data_left = data_len;
size_t data_pos = 0;
/* The payload is larger than MTU (1500 bytes) so we must split it into smaller RTP frames
* Because we don't if the SCD is enabled and thus cannot make any assumptions about the life time
* of current stack, we need to store NAL and FU headers to the frame queue transaction.
/* The payload is larger than MTU (1500 bytes) so we must split it into
* smaller RTP frames, because we cannot make any assumptions about the life time of current stack, we need to store NAL and FU headers to the frame queue transaction.
*
* This can be done by asking a handle to current transaction's buffer vectors.
*

View File

@ -9,7 +9,7 @@
#include "zrtp.hh"
#include "holepuncher.hh"
#include "pkt_dispatch.hh"
#include "reception_flow.hh"
#include "uvgrtp/rtcp.hh"
#include "uvgrtp/socket.hh"
#include "srtp/srtcp.hh"
@ -29,7 +29,7 @@ uvgrtp::media_stream::media_stream(std::string addr, int src_port, int dst_port,
media_config_(nullptr),
initialized_(false),
rtp_handler_key_(0),
pkt_dispatcher_(nullptr),
reception_flow_(nullptr),
media_(nullptr),
holepuncher_(nullptr)
{
@ -56,9 +56,9 @@ uvgrtp::media_stream::media_stream(
uvgrtp::media_stream::~media_stream()
{
if (pkt_dispatcher_)
if (reception_flow_)
{
pkt_dispatcher_->stop();
reception_flow_->stop();
}
// TODO: I would take a close look at what happens when pull_frame is called
@ -127,7 +127,7 @@ rtp_error_t uvgrtp::media_stream::create_media(rtp_format_t fmt)
{
uvgrtp::formats::h264* format_264 = new uvgrtp::formats::h264(socket_, rtp_, ctx_config_.flags);
pkt_dispatcher_->install_aux_handler_cpp(
reception_flow_->install_aux_handler_cpp(
rtp_handler_key_,
std::bind(&uvgrtp::formats::h264::packet_handler, format_264, std::placeholders::_1, std::placeholders::_2),
std::bind(&uvgrtp::formats::h264::frame_getter, format_264, std::placeholders::_1));
@ -140,7 +140,7 @@ rtp_error_t uvgrtp::media_stream::create_media(rtp_format_t fmt)
{
uvgrtp::formats::h265* format_265 = new uvgrtp::formats::h265(socket_, rtp_, ctx_config_.flags);
pkt_dispatcher_->install_aux_handler_cpp(
reception_flow_->install_aux_handler_cpp(
rtp_handler_key_,
std::bind(&uvgrtp::formats::h265::packet_handler, format_265, std::placeholders::_1, std::placeholders::_2),
std::bind(&uvgrtp::formats::h265::frame_getter, format_265, std::placeholders::_1));
@ -153,7 +153,7 @@ rtp_error_t uvgrtp::media_stream::create_media(rtp_format_t fmt)
{
uvgrtp::formats::h266* format_266 = new uvgrtp::formats::h266(socket_, rtp_, ctx_config_.flags);
pkt_dispatcher_->install_aux_handler_cpp(
reception_flow_->install_aux_handler_cpp(
rtp_handler_key_,
std::bind(&uvgrtp::formats::h266::packet_handler, format_266, std::placeholders::_1, std::placeholders::_2),
std::bind(&uvgrtp::formats::h266::frame_getter, format_266, std::placeholders::_1));
@ -166,7 +166,7 @@ rtp_error_t uvgrtp::media_stream::create_media(rtp_format_t fmt)
case RTP_FORMAT_GENERIC:
media_ = new uvgrtp::formats::media(socket_, rtp_, ctx_config_.flags);
pkt_dispatcher_->install_aux_handler(
reception_flow_->install_aux_handler(
rtp_handler_key_,
media_->get_media_frame_info(),
media_->packet_handler,
@ -204,10 +204,10 @@ rtp_error_t uvgrtp::media_stream::free_resources(rtp_error_t ret)
delete srtcp_;
srtcp_ = nullptr;
}
if (pkt_dispatcher_)
if (reception_flow_)
{
delete pkt_dispatcher_;
pkt_dispatcher_ = nullptr;
delete reception_flow_;
reception_flow_ = nullptr;
}
if (holepuncher_)
{
@ -236,7 +236,7 @@ rtp_error_t uvgrtp::media_stream::init()
return free_resources(RTP_GENERIC_ERROR);
}
pkt_dispatcher_ = new uvgrtp::pkt_dispatcher();
reception_flow_ = new uvgrtp::reception_flow();
rtp_ = new uvgrtp::rtp(fmt_);
@ -244,8 +244,8 @@ rtp_error_t uvgrtp::media_stream::init()
socket_->install_handler(rtcp_, rtcp_->send_packet_handler_vec);
rtp_handler_key_ = pkt_dispatcher_->install_handler(rtp_->packet_handler);
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, rtcp_, rtcp_->recv_packet_handler, nullptr);
rtp_handler_key_ = reception_flow_->install_handler(rtp_->packet_handler);
reception_flow_->install_aux_handler(rtp_handler_key_, rtcp_, rtcp_->recv_packet_handler, nullptr);
if (create_media(fmt_) != RTP_OK)
return free_resources(RTP_MEMORY_ERROR);
@ -261,7 +261,7 @@ rtp_error_t uvgrtp::media_stream::init()
}
initialized_ = true;
return pkt_dispatcher_->start(socket_, ctx_config_.flags);
return reception_flow_->start(socket_, ctx_config_.flags);
}
rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)
@ -273,7 +273,7 @@ rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)
return RTP_GENERIC_ERROR;
}
pkt_dispatcher_ = new uvgrtp::pkt_dispatcher();
reception_flow_ = new uvgrtp::reception_flow();
rtp_ = new uvgrtp::rtp(fmt_);
@ -295,11 +295,11 @@ rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)
socket_->install_handler(rtcp_, rtcp_->send_packet_handler_vec);
socket_->install_handler(srtp_, srtp_->send_packet_handler);
rtp_handler_key_ = pkt_dispatcher_->install_handler(rtp_->packet_handler);
zrtp_handler_key_ = pkt_dispatcher_->install_handler(zrtp->packet_handler);
rtp_handler_key_ = reception_flow_->install_handler(rtp_->packet_handler);
zrtp_handler_key_ = reception_flow_->install_handler(zrtp->packet_handler);
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, rtcp_, rtcp_->recv_packet_handler, nullptr);
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, srtp_, srtp_->recv_packet_handler, nullptr);
reception_flow_->install_aux_handler(rtp_handler_key_, rtcp_, rtcp_->recv_packet_handler, nullptr);
reception_flow_->install_aux_handler(rtp_handler_key_, srtp_, srtp_->recv_packet_handler, nullptr);
if (create_media(fmt_) != RTP_OK)
return free_resources(RTP_MEMORY_ERROR);
@ -318,7 +318,7 @@ rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)
rtp_->set_payload_size(MAX_PAYLOAD - UVG_AUTH_TAG_LENGTH);
initialized_ = true;
return pkt_dispatcher_->start(socket_, ctx_config_.flags);
return reception_flow_->start(socket_, ctx_config_.flags);
}
rtp_error_t uvgrtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
@ -337,7 +337,7 @@ rtp_error_t uvgrtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
if ((flags_ & srtp_flags) != srtp_flags)
return free_resources(RTP_NOT_SUPPORTED);
pkt_dispatcher_ = new uvgrtp::pkt_dispatcher();
reception_flow_ = new uvgrtp::reception_flow();
rtp_ = new uvgrtp::rtp(fmt_);
@ -361,10 +361,10 @@ rtp_error_t uvgrtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
socket_->install_handler(rtcp_, rtcp_->send_packet_handler_vec);
socket_->install_handler(srtp_, srtp_->send_packet_handler);
rtp_handler_key_ = pkt_dispatcher_->install_handler(rtp_->packet_handler);
rtp_handler_key_ = reception_flow_->install_handler(rtp_->packet_handler);
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, rtcp_, rtcp_->recv_packet_handler, nullptr);
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, srtp_, srtp_->recv_packet_handler, nullptr);
reception_flow_->install_aux_handler(rtp_handler_key_, rtcp_, rtcp_->recv_packet_handler, nullptr);
reception_flow_->install_aux_handler(rtp_handler_key_, srtp_, srtp_->recv_packet_handler, nullptr);
if (create_media(fmt_) != RTP_OK)
return free_resources(RTP_MEMORY_ERROR);
@ -383,7 +383,7 @@ rtp_error_t uvgrtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
rtp_->set_payload_size(MAX_PAYLOAD - UVG_AUTH_TAG_LENGTH);
initialized_ = true;
return pkt_dispatcher_->start(socket_, ctx_config_.flags);
return reception_flow_->start(socket_, ctx_config_.flags);
}
rtp_error_t uvgrtp::media_stream::push_frame(uint8_t *data, size_t data_len, int flags)
@ -458,7 +458,7 @@ uvgrtp::frame::rtp_frame *uvgrtp::media_stream::pull_frame()
return nullptr;
}
return pkt_dispatcher_->pull_frame();
return reception_flow_->pull_frame();
}
uvgrtp::frame::rtp_frame *uvgrtp::media_stream::pull_frame(size_t timeout_ms)
@ -469,7 +469,7 @@ uvgrtp::frame::rtp_frame *uvgrtp::media_stream::pull_frame(size_t timeout_ms)
return nullptr;
}
return pkt_dispatcher_->pull_frame(timeout_ms);
return reception_flow_->pull_frame(timeout_ms);
}
rtp_error_t uvgrtp::media_stream::install_receive_hook(void *arg, void (*hook)(void *, uvgrtp::frame::rtp_frame *))
@ -482,7 +482,7 @@ rtp_error_t uvgrtp::media_stream::install_receive_hook(void *arg, void (*hook)(v
if (!hook)
return RTP_INVALID_VALUE;
pkt_dispatcher_->install_receive_hook(arg, hook);
reception_flow_->install_receive_hook(arg, hook);
return RTP_OK;
}
@ -553,7 +553,7 @@ rtp_error_t uvgrtp::media_stream::configure_ctx(int flag, ssize_t value)
if (value <= 0)
return RTP_INVALID_VALUE;
pkt_dispatcher_->set_buffer_size(value);
reception_flow_->set_buffer_size(value);
int buf_size = (int)value;
if ((ret = socket_->setsockopt(SOL_SOCKET, SO_RCVBUF, (const char *)&buf_size, sizeof(int))) != RTP_OK)

View File

@ -30,8 +30,9 @@ namespace uvgrtp {
} active_t;
typedef struct transaction {
/* Each transaction has a unique key which is used by the SCD (if enabled)
* when moving the transactions betwen "queued_" and "free_" */
/* Each transaction has a unique key when moving the transactions
* between "queued_" and "free_" */
uint32_t key = 0;
/* To provide true scatter/gather I/O, each transaction has a buf_vec
@ -77,20 +78,10 @@ namespace uvgrtp {
/* Address of receiver, used by sendmmsg(2) */
sockaddr_in out_addr;
/* Used by the system call dispatcher for transaction deinitialization */
uvgrtp::frame_queue *fqueue = nullptr;
/* If SCD is used, it's absolutely essential to initialize transaction
* by giving the data pointer to frame queue
*
* When the SCD has processed the transaction,
* it will be destroyed freeing the "data_smart" automatically.
*
* If "data_raw" is set instead, the SCD checks if a deallocation callback is provided
* and if so, it will deallocate the memory using the callback
*
* If callback is not provided, SCD will check if "flags" field contains the flag "RTP_COPY"
* which means that uvgRTP has a made a copy of the original chunk and it can be safely freed */
/* The flag "RTP_COPY" means that uvgRTP has a made a copy of the original chunk
* and it can be safely freed */
std::unique_ptr<uint8_t[]> data_smart;
uint8_t *data_raw = nullptr;
@ -157,11 +148,6 @@ namespace uvgrtp {
/* Each media may allocate extra buffers for the transaction struct if need be
*
* These headers must be stored in the transaction structure (instead of into
* caller's stack) because if system call dispatcher is used, the transaction is
* not committed immediately but rather given to SCD. This means that when SCD
* starts working on the transaction, the buffers that were on the caller's stack
* are now invalid and the transaction will fail/garbage will be sent
*
* Return pointer to media headers if they're set
* Return nullptr if they're not set */

View File

@ -1,4 +1,4 @@
#include "pkt_dispatch.hh"
#include "reception_flow.hh"
#include "random.hh"
@ -24,7 +24,7 @@ constexpr size_t RECV_BUFFER_SIZE = 0xffff - IPV4_HDR_SIZE - UDP_HDR_SIZE;
constexpr size_t DEFAULT_INITIAL_BUFFER_SIZE = 4194304;
uvgrtp::pkt_dispatcher::pkt_dispatcher() :
uvgrtp::reception_flow::reception_flow() :
recv_hook_arg_(nullptr),
recv_hook_(nullptr),
should_stop_(true),
@ -37,14 +37,14 @@ uvgrtp::pkt_dispatcher::pkt_dispatcher() :
create_ring_buffer();
}
uvgrtp::pkt_dispatcher::~pkt_dispatcher()
uvgrtp::reception_flow::~reception_flow()
{
destroy_ring_buffer();
// TODO: Delete frames?
}
void uvgrtp::pkt_dispatcher::create_ring_buffer()
void uvgrtp::reception_flow::create_ring_buffer()
{
destroy_ring_buffer();
size_t elements = buffer_size_kbytes_ / RECV_BUFFER_SIZE;
@ -55,7 +55,7 @@ void uvgrtp::pkt_dispatcher::create_ring_buffer()
}
}
void uvgrtp::pkt_dispatcher::destroy_ring_buffer()
void uvgrtp::reception_flow::destroy_ring_buffer()
{
for (int i = 0; i < ring_buffer_.size(); ++i)
{
@ -64,17 +64,17 @@ void uvgrtp::pkt_dispatcher::destroy_ring_buffer()
ring_buffer_.clear();
}
void uvgrtp::pkt_dispatcher::set_buffer_size(ssize_t& value)
void uvgrtp::reception_flow::set_buffer_size(ssize_t& value)
{
buffer_size_kbytes_ = value;
create_ring_buffer();
}
rtp_error_t uvgrtp::pkt_dispatcher::start(uvgrtp::socket *socket, int flags)
rtp_error_t uvgrtp::reception_flow::start(uvgrtp::socket *socket, int flags)
{
should_stop_ = false;
processor_ = std::unique_ptr<std::thread>(new std::thread(&uvgrtp::pkt_dispatcher::process_packet, this, flags));
receiver_ = std::unique_ptr<std::thread>(new std::thread(&uvgrtp::pkt_dispatcher::receiver, this, socket, flags));
processor_ = std::unique_ptr<std::thread>(new std::thread(&uvgrtp::reception_flow::process_packet, this, flags));
receiver_ = std::unique_ptr<std::thread>(new std::thread(&uvgrtp::reception_flow::receiver, this, socket, flags));
// set receiver thread priority to maximum priority
LOG_DEBUG("Trying to set receiver thread realtime priority");
@ -95,7 +95,7 @@ rtp_error_t uvgrtp::pkt_dispatcher::start(uvgrtp::socket *socket, int flags)
return RTP_ERROR::RTP_OK;
}
rtp_error_t uvgrtp::pkt_dispatcher::stop()
rtp_error_t uvgrtp::reception_flow::stop()
{
should_stop_ = true;
process_cond_.notify_all();
@ -113,7 +113,7 @@ rtp_error_t uvgrtp::pkt_dispatcher::stop()
return RTP_OK;
}
rtp_error_t uvgrtp::pkt_dispatcher::install_receive_hook(
rtp_error_t uvgrtp::reception_flow::install_receive_hook(
void *arg,
void (*hook)(void *, uvgrtp::frame::rtp_frame *)
)
@ -127,7 +127,7 @@ rtp_error_t uvgrtp::pkt_dispatcher::install_receive_hook(
return RTP_OK;
}
uvgrtp::frame::rtp_frame *uvgrtp::pkt_dispatcher::pull_frame()
uvgrtp::frame::rtp_frame *uvgrtp::reception_flow::pull_frame()
{
while (frames_.empty() && !should_stop_)
{
@ -145,7 +145,7 @@ uvgrtp::frame::rtp_frame *uvgrtp::pkt_dispatcher::pull_frame()
return frame;
}
uvgrtp::frame::rtp_frame *uvgrtp::pkt_dispatcher::pull_frame(size_t timeout_ms)
uvgrtp::frame::rtp_frame *uvgrtp::reception_flow::pull_frame(size_t timeout_ms)
{
auto start_time = std::chrono::high_resolution_clock::now();
@ -167,7 +167,7 @@ uvgrtp::frame::rtp_frame *uvgrtp::pkt_dispatcher::pull_frame(size_t timeout_ms)
return frame;
}
uint32_t uvgrtp::pkt_dispatcher::install_handler(uvgrtp::packet_handler handler)
uint32_t uvgrtp::reception_flow::install_handler(uvgrtp::packet_handler handler)
{
uint32_t key;
@ -182,7 +182,7 @@ uint32_t uvgrtp::pkt_dispatcher::install_handler(uvgrtp::packet_handler handler)
return key;
}
rtp_error_t uvgrtp::pkt_dispatcher::install_aux_handler(
rtp_error_t uvgrtp::reception_flow::install_aux_handler(
uint32_t key,
void *arg,
uvgrtp::packet_handler_aux handler,
@ -204,7 +204,7 @@ rtp_error_t uvgrtp::pkt_dispatcher::install_aux_handler(
return RTP_OK;
}
rtp_error_t uvgrtp::pkt_dispatcher::install_aux_handler_cpp(uint32_t key,
rtp_error_t uvgrtp::reception_flow::install_aux_handler_cpp(uint32_t key,
std::function<rtp_error_t(int, uvgrtp::frame::rtp_frame**)> handler,
std::function<rtp_error_t(uvgrtp::frame::rtp_frame**)> getter)
{
@ -219,7 +219,7 @@ rtp_error_t uvgrtp::pkt_dispatcher::install_aux_handler_cpp(uint32_t key,
return RTP_OK;
}
void uvgrtp::pkt_dispatcher::return_frame(uvgrtp::frame::rtp_frame *frame)
void uvgrtp::reception_flow::return_frame(uvgrtp::frame::rtp_frame *frame)
{
if (recv_hook_) {
recv_hook_(recv_hook_arg_, frame);
@ -230,7 +230,7 @@ void uvgrtp::pkt_dispatcher::return_frame(uvgrtp::frame::rtp_frame *frame)
}
}
void uvgrtp::pkt_dispatcher::call_aux_handlers(uint32_t key, int flags, uvgrtp::frame::rtp_frame **frame)
void uvgrtp::reception_flow::call_aux_handlers(uint32_t key, int flags, uvgrtp::frame::rtp_frame **frame)
{
rtp_error_t ret;
@ -313,7 +313,7 @@ void uvgrtp::pkt_dispatcher::call_aux_handlers(uint32_t key, int flags, uvgrtp::
}
}
void uvgrtp::pkt_dispatcher::receiver(uvgrtp::socket *socket, int flags)
void uvgrtp::reception_flow::receiver(uvgrtp::socket *socket, int flags)
{
LOG_DEBUG("Start reception loop");
@ -384,7 +384,7 @@ void uvgrtp::pkt_dispatcher::receiver(uvgrtp::socket *socket, int flags)
break;
}
else if (ret != RTP_OK) {
LOG_ERROR("recvfrom(2) failed! Packet dispatcher cannot continue %d!", ret);
LOG_ERROR("recvfrom(2) failed! Reception flow cannot continue %d!", ret);
should_stop_ = true;
break;
}
@ -404,42 +404,7 @@ void uvgrtp::pkt_dispatcher::receiver(uvgrtp::socket *socket, int flags)
}
}
/* The point of packet dispatcher is to provide isolation between different layers
* of uvgRTP. For example, HEVC handler should not concern itself with RTP packet validation
* because that should be a global operation done for all packets. Neither should Opus handler
* take SRTP-provided authentication tag into account when it is performing operations on
* the packet and ZRTP packets should not be relayed from media handler
* to ZRTP handler et cetera.
*
* This can be achieved by having a global UDP packet handler for any packet type that validates
* all common stuff it can and then dispatches the validated packet to the correct layer using
* one of the installed handlers.
*
* If it's unclear as to which handler should be called, the packet is dispatched to all relevant
* handlers and a handler then returns RTP_OK/RTP_PKT_NOT_HANDLED based on whether the packet was handled.
*
* For example, if runner detects an incoming ZRTP packet, that packet is immediately dispatched to the
* installed ZRTP handler if ZRTP has been enabled.
* Likewise, if RTP packet authentication has been enabled, runner validates the packet before passing
* it onto any other layer so all future work on the packet is not done in vain due to invalid data
*
* One piece of design choice that complicates the design of packet dispatcher a little is that the order
* of handlers is important. First handler must be ZRTP and then follows SRTP, RTP and finally media handlers.
* This requirement gives packet handler a clean and generic interface while giving a possibility to modify
* the packet in each of the called handlers if needed. For example SRTP handler verifies RTP authentication
* tag and decrypts the packet and RTP handler verifies the fields of the RTP packet and processes it into
* a more easily modifiable format for the media handler.
*
* If packet is modified by the handler but the frame is not ready to be returned to user,
* handler returns RTP_PKT_MODIFIED to indicate that it has modified the input buffer and that
* the packet should be passed onto other handlers.
*
* When packet is ready to be returned to user, "out" parameter of packet handler is set to point to
* the allocated frame that can be returned and return value of the packet handler is RTP_PKT_READY.
*
* If a handler receives a non-null "out", it can safely ignore "packet" and operate just on
* the "out" parameter because at that point it already contains all needed information. */
void uvgrtp::pkt_dispatcher::process_packet(int flags)
void uvgrtp::reception_flow::process_packet(int flags)
{
LOG_DEBUG("Start processing loop");
std::unique_lock<std::mutex> lk(wait_mtx_);
@ -501,7 +466,7 @@ void uvgrtp::pkt_dispatcher::process_packet(int flags)
}
}
int uvgrtp::pkt_dispatcher::next_buffer_location(int current_location)
int uvgrtp::reception_flow::next_buffer_location(int current_location)
{
return (current_location + 1) % ring_buffer_.size();
}

View File

@ -40,10 +40,49 @@ namespace uvgrtp {
std::vector<auxiliary_handler_cpp> auxiliary_cpp;
};
class pkt_dispatcher{
/* This class handles the reception processing of received RTP packets. It
* utilizes function dispatching to other classes to achieve this.
* The point of reception flow is to provide isolation between different layers
* of uvgRTP. For example, HEVC handler should not concern itself with RTP packet validation
* because that should be a global operation done for all packets. Neither should Opus handler
* take SRTP-provided authentication tag into account when it is performing operations on
* the packet and ZRTP packets should not be relayed from media handler
* to ZRTP handler et cetera.
*
* This can be achieved by having a global UDP packet handler for any packet type that validates
* all common stuff it can and then dispatches the validated packet to the correct layer using
* one of the installed handlers.
*
* If it's unclear as to which handler should be called, the packet is dispatched to all relevant
* handlers and a handler then returns RTP_OK/RTP_PKT_NOT_HANDLED based on whether the packet was handled.
*
* For example, if runner detects an incoming ZRTP packet, that packet is immediately dispatched to the
* installed ZRTP handler if ZRTP has been enabled.
* Likewise, if RTP packet authentication has been enabled, runner validates the packet before passing
* it onto any other layer so all future work on the packet is not done in vain due to invalid data
*
* One piece of design choice that complicates the design of packet dispatcher a little is that the order
* of handlers is important. First handler must be ZRTP and then follows SRTP, RTP and finally media handlers.
* This requirement gives packet handler a clean and generic interface while giving a possibility to modify
* the packet in each of the called handlers if needed. For example SRTP handler verifies RTP authentication
* tag and decrypts the packet and RTP handler verifies the fields of the RTP packet and processes it into
* a more easily modifiable format for the media handler.
*
* If packet is modified by the handler but the frame is not ready to be returned to user,
* handler returns RTP_PKT_MODIFIED to indicate that it has modified the input buffer and that
* the packet should be passed onto other handlers.
*
* When packet is ready to be returned to user, "out" parameter of packet handler is set to point to
* the allocated frame that can be returned and return value of the packet handler is RTP_PKT_READY.
*
* If a handler receives a non-null "out", it can safely ignore "packet" and operate just on
* the "out" parameter because at that point it already contains all needed information. */
class reception_flow{
public:
pkt_dispatcher();
~pkt_dispatcher();
reception_flow();
~reception_flow();
/* Install a primary handler for an incoming UDP datagram
*
@ -77,20 +116,20 @@ namespace uvgrtp {
std::function<rtp_error_t(int, uvgrtp::frame::rtp_frame**)> handler,
std::function<rtp_error_t(uvgrtp::frame::rtp_frame**)> getter);
/* Install receive hook for the RTP packet dispatcher
/* Install receive hook in reception flow
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if "hook" is nullptr */
rtp_error_t install_receive_hook(void *arg, void (*hook)(void *, uvgrtp::frame::rtp_frame *));
/* Start the RTP packet dispatcher
/* Start the RTP reception flow. Start querying for received packets and processing them.
*
* Return RTP_OK on success
* Return RTP_MEMORY_ERROR if allocation of a thread object fails */
rtp_error_t start(uvgrtp::socket *socket, int flags);
/* Stop the RTP packet dispatcher and wait until the receive loop is exited
* to make sure that destroying the object in media_stream.cc is safe
/* Stop the RTP reception flow and wait until the receive loop is exited
* to make sure that destroying the object is safe.
*
* Return RTP_OK on success */
rtp_error_t stop();

View File

@ -36,7 +36,7 @@ uvgrtp::media_stream *uvgrtp::session::create_stream(int r_port, int s_port, rtp
uvgrtp::media_stream *stream = nullptr;
if (flags & RCE_SYSTEM_CALL_DISPATCHER) {
LOG_ERROR("SCD is not supported!");
LOG_ERROR("SCD is no longer supported!");
rtp_errno = RTP_NOT_SUPPORTED;
return nullptr;
}

View File

@ -205,7 +205,7 @@ namespace uvgrtp {
);
/* ZRTP packet handler is used after ZRTP state initialization has finished
* and media exchange has started. RTP packet dispatcher gives the packet
* and media exchange has started. RTP reception flow gives the packet
* to "zrtp_handler" which then checks whether the packet is a ZRTP packet
* or not and processes it accordingly.
*

View File

@ -31,7 +31,7 @@ namespace uvgrtp {
ssize_t get_msg(void *ptr, size_t len);
/* ZRTP packet handler is used after ZRTP state initialization has finished
* and media exchange has started. RTP packet dispatcher gives the packet
* and media exchange has started. RTP reception flow gives the packet
* to "zrtp_handler" which then checks whether the packet is a ZRTP packet
* or not and processes it accordingly.
*