Implement packet handler support for outgoing frames

uvgRTP can install handler f.ex. for collecting RTCP sender statistics
information or to install SRTP encryption handler.

This way these unrelated objects don't have to be passed to src/socket.cc
and it will only contain code pertaining to actual socket operations
This commit is contained in:
Aaro Altonen 2020-08-12 11:31:30 +03:00
parent 9ee2318384
commit 906f6e6853
2 changed files with 130 additions and 0 deletions

View File

@ -27,6 +27,18 @@ namespace uvg_rtp {
const int MAX_BUFFER_COUNT = 256;
typedef rtp_error_t (*packet_handler_buf)(void *, ssize_t, void *);
typedef rtp_error_t (*packet_handler_vec)(void *, std::vector<std::pair<size_t, uint8_t *>>&);
struct socket_packet_handler {
void *arg;
union {
packet_handler_buf buf;
packet_handler_vec vec;
} handlers;
};
class socket {
public:
socket(int flags);
@ -138,6 +150,16 @@ namespace uvg_rtp {
/* Get the out address for the socket if it exists */
sockaddr_in& get_out_address();
/* Install a packet handler for buffer- or vector-based send operations.
*
* These handlers allow the caller to inject extra functionality to the send operation
* without polluting src/socket.cc with unrelated code
* (such as collecting RTCP session statistics info or encrypting a packet)
*
* "arg" is an optional parameter that can be passed to the handler when it's called */
rtp_error_t install_handler(void *arg, packet_handler_buf handler);
rtp_error_t install_handler(void *arg, packet_handler_vec handler);
private:
/* helper function for sending UPD packets, see documentation for sendto() above */
rtp_error_t __sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int flags, int *bytes_sent);
@ -152,6 +174,12 @@ namespace uvg_rtp {
uvg_rtp::srtp *srtp_;
int flags_;
/* __sendto() calls these handlers in order before sending the packet*/
std::vector<socket_packet_handler> buf_handlers_;
/* __sendtov() calls these handlers in order before sending the packet */
std::vector<socket_packet_handler> vec_handlers_;
#ifdef _WIN32
WSABUF buffers_[MAX_BUFFER_COUNT];
#else

View File

@ -135,6 +135,36 @@ socket_t& uvg_rtp::socket::get_raw_socket()
return socket_;
}
rtp_error_t uvg_rtp::socket::install_handler(void *arg, packet_handler_buf handler)
{
if (!handler)
return RTP_INVALID_VALUE;
socket_packet_handler hndlr;
hndlr.arg = arg;
hndlr.handlers.buf = handler;
buf_handlers_.push_back(hndlr);
return RTP_OK;
}
rtp_error_t uvg_rtp::socket::install_handler(void *arg, packet_handler_vec handler)
{
if (!handler)
return RTP_INVALID_VALUE;
socket_packet_handler hndlr;
hndlr.arg = arg;
hndlr.handlers.vec = handler;
vec_handlers_.push_back(hndlr);
return RTP_OK;
}
rtp_error_t uvg_rtp::socket::__sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int flags, int *bytes_sent)
{
int nsend = 0;
@ -172,21 +202,57 @@ rtp_error_t uvg_rtp::socket::__sendto(sockaddr_in& addr, uint8_t *buf, size_t bu
rtp_error_t uvg_rtp::socket::sendto(uint8_t *buf, size_t buf_len, int flags)
{
rtp_error_t ret;
for (auto& handler : buf_handlers_) {
if ((ret = (*handler.handlers.buf)(handler.arg, buf_len, buf)) != RTP_OK) {
LOG_ERROR("Malfored packet %p %zu %d", buf, buf_len, flags);
return ret;
}
}
return __sendto(addr_, buf, buf_len, flags, nullptr);
}
rtp_error_t uvg_rtp::socket::sendto(uint8_t *buf, size_t buf_len, int flags, int *bytes_sent)
{
rtp_error_t ret;
for (auto& handler : buf_handlers_) {
if ((ret = (*handler.handlers.buf)(handler.arg, buf_len, buf)) != RTP_OK) {
LOG_ERROR("Malfored packet %p %zu %d", buf, buf_len, flags);
return ret;
}
}
return __sendto(addr_, buf, buf_len, flags, bytes_sent);
}
rtp_error_t uvg_rtp::socket::sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int flags, int *bytes_sent)
{
rtp_error_t ret;
for (auto& handler : buf_handlers_) {
if ((ret = (*handler.handlers.buf)(handler.arg, buf_len, buf)) != RTP_OK) {
LOG_ERROR("Malfored packet %p %zu %d", buf, buf_len, flags);
return ret;
}
}
return __sendto(addr, buf, buf_len, flags, bytes_sent);
}
rtp_error_t uvg_rtp::socket::sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int flags)
{
rtp_error_t ret;
for (auto& handler : buf_handlers_) {
if ((ret = (*handler.handlers.buf)(handler.arg, buf_len, buf)) != RTP_OK) {
LOG_ERROR("Malfored packet %p %zu %d", buf, buf_len, flags);
return ret;
}
}
return __sendto(addr, buf, buf_len, flags, nullptr);
}
@ -261,16 +327,43 @@ rtp_error_t uvg_rtp::socket::__sendtov(
rtp_error_t uvg_rtp::socket::sendto(std::vector<std::pair<size_t, uint8_t *>> buffers, int flags)
{
rtp_error_t ret;
for (auto& handler : buf_handlers_) {
if ((ret = (*handler.handlers.vec)(handler.arg, buffers)) != RTP_OK) {
LOG_ERROR("Malfored packet");
return ret;
}
}
return __sendtov(addr_, buffers, flags, nullptr);
}
rtp_error_t uvg_rtp::socket::sendto(std::vector<std::pair<size_t, uint8_t *>> buffers, int flags, int *bytes_sent)
{
rtp_error_t ret;
for (auto& handler : buf_handlers_) {
if ((ret = (*handler.handlers.vec)(handler.arg, buffers)) != RTP_OK) {
LOG_ERROR("Malfored packet");
return ret;
}
}
return __sendtov(addr_, buffers, flags, bytes_sent);
}
rtp_error_t uvg_rtp::socket::sendto(sockaddr_in& addr, std::vector<std::pair<size_t, uint8_t *>> buffers, int flags)
{
rtp_error_t ret;
for (auto& handler : buf_handlers_) {
if ((ret = (*handler.handlers.vec)(handler.arg, buffers)) != RTP_OK) {
LOG_ERROR("Malfored packet");
return ret;
}
}
return __sendtov(addr, buffers, flags, nullptr);
}
@ -280,6 +373,15 @@ rtp_error_t uvg_rtp::socket::sendto(
int flags, int *bytes_sent
)
{
rtp_error_t ret;
for (auto& handler : buf_handlers_) {
if ((ret = (*handler.handlers.vec)(handler.arg, buffers)) != RTP_OK) {
LOG_ERROR("Malfored packet");
return ret;
}
}
return __sendtov(addr, buffers, flags, bytes_sent);
}