uvgrtp-base/include/pkt_dispatch.hh

115 lines
4.7 KiB
C++

#pragma once
#include <mutex>
#include <unordered_map>
#include "frame.hh"
#include "runner.hh"
#include "socket.hh"
#include "util.hh"
namespace uvgrtp {
typedef rtp_error_t (*packet_handler)(ssize_t, void *, int, uvgrtp::frame::rtp_frame **);
typedef rtp_error_t (*packet_handler_aux)(void *, int, uvgrtp::frame::rtp_frame **);
typedef rtp_error_t (*frame_getter)(void *, uvgrtp::frame::rtp_frame **);
struct auxiliary_handler {
void *arg;
packet_handler_aux handler;
frame_getter getter;
};
struct packet_handlers {
packet_handler primary;
std::vector<auxiliary_handler> auxiliary;
};
class pkt_dispatcher : public runner {
public:
pkt_dispatcher();
~pkt_dispatcher();
/* Install a primary handler for an incoming UDP datagram
*
* This handler is responsible for creating an operable RTP packet
* that auxiliary handlers can work with.
*
* It is also responsible for validating the packet on a high level
* (ZRTP checksum/RTP version etc) before passing it onto other handlers.
*
* Return a key on success that differentiates primary packet handlers
* Return 0 "handler" is nullptr */
uint32_t install_handler(packet_handler handler);
/* Install auxiliary handler for the packet
*
* This handler is responsible for doing auxiliary operations on the packet
* such as gathering sessions statistics data or decrypting the packet
* It is called only after the primary handler of the auxiliary handler is called
*
* "key" is used to specify for which primary handlers for "handler"
* An auxiliary handler can be installed to multiple primary handlers
*
* "arg" is an optional argument that is passed to the handler when it's called
* It can be null if the handler does not require additional data
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if "handler" is nullptr or if "key" is not valid */
rtp_error_t install_aux_handler(uint32_t key, void *arg, packet_handler_aux handler, frame_getter getter);
/* Install receive hook for the RTP packet dispatcher
*
* 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
*
* 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
*
* Return RTP_OK on success */
rtp_error_t stop();
/* Fetch frame from the frame queue that contains all received frame.
* pull_frame() will block until there is a frame that can be returned.
* If "timeout" is given, pull_frame() will block only for however long
* that value tells it to.
* If no frame is received within that time period, pull_frame() returns nullptr
*
* Return pointer to RTP frame on success
* Return nullptr if operation timed out or an error occurred */
uvgrtp::frame::rtp_frame *pull_frame();
uvgrtp::frame::rtp_frame *pull_frame(size_t ms);
private:
/* RTP packet dispatcher thread */
void runner(uvgrtp::socket *socket, int flags);
/* Return a processed RTP frame to user either through frame queue or receive hook */
void return_frame(uvgrtp::frame::rtp_frame *frame);
/* Call auxiliary handlers of a primary handler */
void call_aux_handlers(uint32_t key, int flags, uvgrtp::frame::rtp_frame **frame);
/* Primary handlers for the socket */
std::unordered_map<uint32_t, packet_handlers> packet_handlers_;
/* If receive hook has not been installed, frames are pushed to "frames_"
* and they can be retrieved using pull_frame() */
std::vector<uvgrtp::frame::rtp_frame *> frames_;
std::mutex frames_mtx_;
std::mutex exit_mtx_;
void *recv_hook_arg_;
void (*recv_hook_)(void *arg, uvgrtp::frame::rtp_frame *frame);
};
}
namespace uvg_rtp = uvgrtp;