Merge branch 'security-fixes' into develop
This commit is contained in:
commit
b51fef61ee
|
@ -33,3 +33,11 @@ See [BUILDING.md](BUILDING.md) for instructions on how to build and use uvgRTP
|
|||
## Examples
|
||||
|
||||
See [examples](examples/) directory for different uvgRTP examples
|
||||
|
||||
## Paper
|
||||
|
||||
Please cite the following paper for uvgRTP:
|
||||
|
||||
```
|
||||
A. Altonen, J. Räsänen, J. Laitinen, M. Viitanen, and J. Vanne, “Open-source RTP library for high-speed 4K HEVC video streaming,” Accepted to IEEE Int. Workshop on Multimedia Signal Processing, Tampere, Finland, Sept. 2020.
|
||||
```
|
||||
|
|
|
@ -139,6 +139,7 @@ namespace uvg_rtp {
|
|||
namespace crc32 {
|
||||
void get_crc32(uint8_t *input, size_t len, uint32_t *output);
|
||||
bool verify_crc32(uint8_t *input, size_t len, uint32_t old_crc);
|
||||
uint32_t calculate_crc32(uint8_t *input, size_t len);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "../rtp.hh"
|
||||
#include "../socket.hh"
|
||||
#include "../queue.hh"
|
||||
#include "../util.hh"
|
||||
|
||||
namespace uvg_rtp {
|
||||
|
@ -41,6 +42,7 @@ namespace uvg_rtp {
|
|||
uvg_rtp::socket *socket_;
|
||||
uvg_rtp::rtp *rtp_ctx_;
|
||||
int flags_;
|
||||
uvg_rtp::frame_queue *fqueue_;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -174,10 +174,10 @@ namespace uvg_rtp {
|
|||
|
||||
uint32_t key_;
|
||||
|
||||
uvg_rtp::srtp *srtp_;
|
||||
uvg_rtp::socket socket_;
|
||||
uvg_rtp::rtp *rtp_;
|
||||
uvg_rtp::rtcp *rtcp_;
|
||||
uvg_rtp::srtp *srtp_;
|
||||
uvg_rtp::socket *socket_;
|
||||
uvg_rtp::rtp *rtp_;
|
||||
uvg_rtp::rtcp *rtcp_;
|
||||
|
||||
sockaddr_in addr_out_;
|
||||
std::string addr_;
|
||||
|
@ -199,8 +199,9 @@ namespace uvg_rtp {
|
|||
/* media stream type */
|
||||
enum mstream_type type_;
|
||||
|
||||
/* Primary handler's key for the RTP packet dispatcher */
|
||||
/* Primary handler keys for the RTP packet dispatcher */
|
||||
uint32_t rtp_handler_key_;
|
||||
uint32_t zrtp_handler_key_;
|
||||
|
||||
/* RTP packet dispatcher for the receiver */
|
||||
uvg_rtp::pkt_dispatcher *pkt_dispatcher_;
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace uvg_rtp {
|
|||
|
||||
namespace zrtp_msg {
|
||||
|
||||
struct zrtp_confack {
|
||||
PACKED_STRUCT(zrtp_confack) {
|
||||
zrtp_msg msg_start;
|
||||
uint32_t crc;
|
||||
};
|
||||
|
|
|
@ -43,6 +43,25 @@ namespace uvg_rtp {
|
|||
ZRTP_FT_PING_ACK = 13
|
||||
};
|
||||
|
||||
enum ZRTP_MSG_TYPE {
|
||||
ZRTP_MSG_HELLO = 0x2020206f6c6c6548,
|
||||
ZRTP_MSG_HELLO_ACK = 0x4b43416f6c6c6548,
|
||||
ZRTP_MSG_COMMIT = 0x202074696d6d6f43,
|
||||
ZRTP_MSG_DH_PART1 = 0x2031747261504844,
|
||||
ZRTP_MSG_DH_PART2 = 0x2032747261504844,
|
||||
ZRTP_MSG_CONFIRM1 = 0x316d7269666e6f43,
|
||||
ZRTP_MSG_CONFIRM2 = 0x326d7269666e6f43,
|
||||
ZRTP_MSG_CONF2_ACK = 0x4b434132666e6f43,
|
||||
ZRTP_MSG_ERROR = 0x202020726f727245,
|
||||
ZRTP_MSG_ERROR_ACK = 0x4b4341726f727245,
|
||||
ZRTP_MSG_GO_CLEAR = 0x207261656c436f47,
|
||||
ZRTP_MSG_CLEAR_ACK = 0x4b43417261656c43,
|
||||
ZRTP_MSG_SAS_RELAY = 0x79616c6572534153,
|
||||
ZRTP_MSG_RELAY_ACK = 0x4b434179616c6552,
|
||||
ZRTP_MSG_PING = 0x20202020676e6950,
|
||||
ZRTP_MSG_PING_ACK = 0x204b4341676e6950,
|
||||
};
|
||||
|
||||
enum MAGIC {
|
||||
ZRTP_HEADER_MAGIC = 0x5a525450,
|
||||
ZRTP_MSG_MAGIC = 0x0000505a,
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace uvg_rtp {
|
|||
|
||||
namespace zrtp_msg {
|
||||
|
||||
struct zrtp_dh {
|
||||
PACKED_STRUCT(zrtp_dh) {
|
||||
zrtp_msg msg_start;
|
||||
uint32_t hash[8];
|
||||
uint8_t rs1_id[8];
|
||||
|
|
|
@ -29,19 +29,21 @@ namespace uvg_rtp {
|
|||
size_t c_start; size_t c_end;
|
||||
} active_t;
|
||||
|
||||
typedef std::vector<std::pair<size_t, uint8_t *>> buff_vec;
|
||||
|
||||
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_" */
|
||||
uint32_t key;
|
||||
|
||||
/* To provide true scatter/gather I/O, each transaction has a buff_vec
|
||||
/* To provide true scatter/gather I/O, each transaction has a buf_vec
|
||||
* structure which may contain differents buffers and their sizes.
|
||||
*
|
||||
* This can be used, for example, for storing media-specific headers
|
||||
* which are then passed (along with the actual media) to enqueue_message() */
|
||||
uvg_rtp::buff_vec buffers;
|
||||
uvg_rtp::buf_vec buffers;
|
||||
|
||||
/* Each RTP frame of a transaction is constructed using buf_vec structure and
|
||||
* each buf_vec structure is pushed to pkt_vec */
|
||||
uvg_rtp::pkt_vec packets;
|
||||
|
||||
/* All packets of a transaction share the common RTP header only differing in sequence number.
|
||||
* Keeping a separate common RTP header and then just copying this is cleaner than initializing
|
||||
|
@ -64,9 +66,13 @@ namespace uvg_rtp {
|
|||
* See src/formats/hevc.hh for example */
|
||||
void *media_headers;
|
||||
|
||||
/* Pointer to RTP authentication (if enabled) */
|
||||
uint64_t *rtp_auth_tags;
|
||||
|
||||
size_t chunk_ptr;
|
||||
size_t hdr_ptr;
|
||||
size_t rtphdr_ptr;
|
||||
size_t rtpauth_ptr;
|
||||
|
||||
/* Address of receiver, used by sendmmsg(2) */
|
||||
sockaddr_in out_addr;
|
||||
|
@ -96,9 +102,7 @@ namespace uvg_rtp {
|
|||
|
||||
class frame_queue {
|
||||
public:
|
||||
/* frame_queue(rtp_format_t fmt); */
|
||||
/* frame_queue(rtp_format_t fmt, uvg_rtp::dispatcher *dispatcher); */
|
||||
frame_queue(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp);
|
||||
frame_queue(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp, int flags);
|
||||
~frame_queue();
|
||||
|
||||
rtp_error_t init_transaction();
|
||||
|
@ -134,7 +138,7 @@ namespace uvg_rtp {
|
|||
* Return RTP_OK on success
|
||||
* Return RTP_INVALID_VALUE if one of the parameters is invalid
|
||||
* Return RTP_MEMORY_ERROR if the maximum amount of chunks/messages is exceeded */
|
||||
rtp_error_t enqueue_message(buff_vec& buffers);
|
||||
rtp_error_t enqueue_message(buf_vec& buffers);
|
||||
|
||||
/* Flush the message queue
|
||||
*
|
||||
|
@ -147,8 +151,8 @@ namespace uvg_rtp {
|
|||
* These headers must be valid until the message is sent (ie. they cannot be saved to
|
||||
* caller's stack).
|
||||
*
|
||||
* Buff_vec is the place to store these extra headers (see src/formats/hevc.cc) */
|
||||
uvg_rtp::buff_vec& get_buffer_vector();
|
||||
* buf_vec is the place to store these extra headers (see src/formats/hevc.cc) */
|
||||
uvg_rtp::buf_vec& get_buffer_vector();
|
||||
|
||||
/* Each media may allocate extra buffers for the transaction struct if need be
|
||||
*
|
||||
|
@ -209,5 +213,8 @@ namespace uvg_rtp {
|
|||
|
||||
uvg_rtp::rtp *rtp_;
|
||||
uvg_rtp::socket *socket_;
|
||||
|
||||
/* RTP context flags */
|
||||
int flags_;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace uvg_rtp {
|
|||
|
||||
class connection;
|
||||
|
||||
enum ROLE {
|
||||
enum RTCP_ROLE {
|
||||
RECEIVER,
|
||||
SENDER
|
||||
};
|
||||
|
@ -200,8 +200,7 @@ namespace uvg_rtp {
|
|||
static rtp_error_t recv_packet_handler(void *arg, int flags, frame::rtp_frame **out);
|
||||
|
||||
/* Update RTCP-related sender statistics */
|
||||
static rtp_error_t send_packet_handler_buf(void *arg, ssize_t len, void *buf);
|
||||
static rtp_error_t send_packet_handler_vec(void *arg, std::vector<std::pair<size_t, uint8_t *>>& buffers);
|
||||
static rtp_error_t send_packet_handler_vec(void *arg, uvg_rtp::buf_vec& buffers);
|
||||
|
||||
private:
|
||||
static void rtcp_runner(rtcp *rtcp);
|
||||
|
|
|
@ -18,25 +18,19 @@
|
|||
|
||||
namespace uvg_rtp {
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef unsigned socklen_t;
|
||||
typedef TRANSMIT_PACKETS_ELEMENT vecio_buf;
|
||||
#else
|
||||
typedef mmsghdr vecio_buf;
|
||||
#endif
|
||||
|
||||
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 *>>&);
|
||||
/* Vector of buffers that contain a full RTP frame */
|
||||
typedef std::vector<std::pair<size_t, uint8_t *>> buf_vec;
|
||||
|
||||
/* Vector of RTP frames constructed from buf_vec entries */
|
||||
typedef std::vector<std::vector<std::pair<size_t, uint8_t *>>> pkt_vec;
|
||||
|
||||
typedef rtp_error_t (*packet_handler_vec)(void *, buf_vec&);
|
||||
|
||||
struct socket_packet_handler {
|
||||
void *arg;
|
||||
|
||||
union {
|
||||
packet_handler_buf buf;
|
||||
packet_handler_vec vec;
|
||||
} handlers;
|
||||
packet_handler_vec handler;
|
||||
};
|
||||
|
||||
class socket {
|
||||
|
@ -76,35 +70,18 @@ namespace uvg_rtp {
|
|||
* Return RTP_SEND_ERROR on error and set "bytes_sent" to -1 */
|
||||
rtp_error_t sendto(uint8_t *buf, size_t buf_len, int flags);
|
||||
rtp_error_t sendto(uint8_t *buf, size_t buf_len, int flags, int *bytes_sent);
|
||||
rtp_error_t sendto(std::vector<std::pair<size_t, uint8_t *>> buffers, int flags);
|
||||
rtp_error_t sendto(std::vector<std::pair<size_t, uint8_t *>> buffers, int flags, int *bytes_sent);
|
||||
rtp_error_t sendto(buf_vec& buffers, int flags);
|
||||
rtp_error_t sendto(buf_vec& buffers, int flags, int *bytes_sent);
|
||||
rtp_error_t sendto(pkt_vec& buffers, int flags);
|
||||
rtp_error_t sendto(pkt_vec& buffers, int flags, int *bytes_sent);
|
||||
|
||||
/* Same as sendto() but the remote address given as parameter */
|
||||
rtp_error_t sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int flags);
|
||||
rtp_error_t sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int flags, int *bytes_sent);
|
||||
rtp_error_t sendto(sockaddr_in& addr, std::vector<std::pair<size_t, uint8_t *>> buffers, int flags);
|
||||
rtp_error_t sendto(sockaddr_in& addr, std::vector<std::pair<size_t, uint8_t *>> buffers, int flags, int *bytes_sent);
|
||||
|
||||
/* Special sendto() function, used to send multiple UDP packets with one system call
|
||||
* Internally it uses sendmmsg(2) (Linux) or TransmitPackets (Windows)
|
||||
*
|
||||
* Return RTP_OK on success
|
||||
* Return RTP_INVALID_VALUE if one of the parameters is invalid
|
||||
* Return RTP_SEND_ERROR if sendmmsg/TransmitPackets failed */
|
||||
rtp_error_t send_vecio(vecio_buf *buffers, size_t nbuffers, int flags);
|
||||
|
||||
/* Special recv() function, used to receive multiple UDP packets with one system call
|
||||
* Internally it uses recvmmsg(2) (Linux).
|
||||
*
|
||||
* TODO what about windows?
|
||||
*
|
||||
* Parameter "nread" is used to indicate how many packet were read from the OS.
|
||||
* It may differ from "nbuffers"
|
||||
*
|
||||
* Return RTP_OK on success
|
||||
* Return RTP_INVALID_VALUE if one of the parameters is invalid
|
||||
* Return RTP_SEND_ERROR if sendmmsg/TransmitPackets failed */
|
||||
rtp_error_t recv_vecio(vecio_buf *buffers, size_t nbuffers, int flags, int *nread);
|
||||
rtp_error_t sendto(sockaddr_in& addr, buf_vec& buffers, int flags);
|
||||
rtp_error_t sendto(sockaddr_in& addr, buf_vec& buffers, int flags, int *bytes_sent);
|
||||
rtp_error_t sendto(sockaddr_in& addr, pkt_vec& buffers, int flags);
|
||||
rtp_error_t sendto(sockaddr_in& addr, pkt_vec& buffers, int flags, int *bytes_sent);
|
||||
|
||||
/* Same as recv(2), receives a message from socket (remote address not known)
|
||||
*
|
||||
|
@ -144,20 +121,16 @@ namespace uvg_rtp {
|
|||
* This is used when calling send() */
|
||||
void set_sockaddr(sockaddr_in addr);
|
||||
|
||||
/* TODO: */
|
||||
void set_srtp(uvg_rtp::srtp *srtp);
|
||||
|
||||
/* 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.
|
||||
/* Install a packet handler for vector-based send operations.
|
||||
*
|
||||
* These handlers allow the caller to inject extra functionality to the send operation
|
||||
* This handler allows 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:
|
||||
|
@ -167,11 +140,11 @@ namespace uvg_rtp {
|
|||
rtp_error_t __recvfrom(uint8_t *buf, size_t buf_len, int flags, sockaddr_in *sender, int *bytes_read);
|
||||
|
||||
/* __sendtov() does the same as __sendto but it combines multiple buffers into one frame and sends them */
|
||||
rtp_error_t __sendtov(sockaddr_in& addr, std::vector<std::pair<size_t, uint8_t *>> buffers, int flags, int *bytes_sent);
|
||||
rtp_error_t __sendtov(sockaddr_in& addr, buf_vec& buffers, int flags, int *bytes_sent);
|
||||
rtp_error_t __sendtov(sockaddr_in& addr, uvg_rtp::pkt_vec& buffers, int flags, int *bytes_sent);
|
||||
|
||||
socket_t socket_;
|
||||
sockaddr_in addr_;
|
||||
uvg_rtp::srtp *srtp_;
|
||||
int flags_;
|
||||
|
||||
/* __sendto() calls these handlers in order before sending the packet*/
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "debug.hh"
|
||||
#include "frame.hh"
|
||||
|
@ -27,6 +28,9 @@
|
|||
|
||||
namespace uvg_rtp {
|
||||
|
||||
/* Vector of buffers that contain a full RTP frame */
|
||||
typedef std::vector<std::pair<size_t, uint8_t *>> buf_vec;
|
||||
|
||||
enum STYPE {
|
||||
SRTP = 0,
|
||||
SRTCP = 1
|
||||
|
@ -100,6 +104,8 @@ namespace uvg_rtp {
|
|||
/* following fields are receiver-only */
|
||||
uint16_t s_l; /* highest received sequence number */
|
||||
uint8_t *replay; /* list of recently received and authenticated SRTP packets */
|
||||
|
||||
srtp_key_ctx_t key_ctx;
|
||||
} srtp_ctx_t;
|
||||
|
||||
class srtp {
|
||||
|
@ -125,21 +131,8 @@ namespace uvg_rtp {
|
|||
* Return RTP_MEMORY allocation failed */
|
||||
rtp_error_t init_user(int type, int flags, uint8_t *key, uint8_t *salt);
|
||||
|
||||
/* Encrypt the payload of "frame" using the private session key
|
||||
*
|
||||
* Return RTP_OK on success
|
||||
* Return RTP_INVALID_VALUE if "frame" is nullptr
|
||||
* Return RTP_NOT_INITIALIZED if SRTP has not been initialized */
|
||||
rtp_error_t encrypt(uvg_rtp::frame::rtp_frame *frame);
|
||||
|
||||
/* Encrypt the payload of "buffers" vector using the private session key
|
||||
* The payload that is encrypted is the last buffer of "buffers" and the
|
||||
* RTP header is the first" buffer of "buffers"
|
||||
*
|
||||
* Return RTP_OK on success
|
||||
* Return RTP_INVALID_VALUE if "frame" is nullptr
|
||||
* Return RTP_NOT_INITIALIZED if SRTP has not been initialized */
|
||||
rtp_error_t encrypt(std::vector<std::pair<size_t, uint8_t *>>& buffers);
|
||||
/* TODO: */
|
||||
rtp_error_t encrypt(uint32_t ssrc, uint16_t seq, uint8_t *buffer, size_t len);
|
||||
|
||||
/* Decrypt the payload payload of "frame" using the private session key
|
||||
*
|
||||
|
@ -157,6 +150,21 @@ namespace uvg_rtp {
|
|||
* Return RTP_OK on success
|
||||
* Return RTP_INVALID_VALUE if "frame" is nullptr or if authentication failed */
|
||||
rtp_error_t authenticate(uvg_rtp::frame::rtp_frame *frame);
|
||||
|
||||
/* Has RTP packet encryption been disabled? */
|
||||
bool use_null_cipher();
|
||||
|
||||
/* Has RTP packet authentication been enabled? */
|
||||
bool authenticate_rtp();
|
||||
|
||||
/* Get reference to the SRTP context (including session keys) */
|
||||
srtp_ctx_t& get_ctx();
|
||||
|
||||
/* Decrypt the payload and verify authentication tag (if enabled) */
|
||||
static rtp_error_t recv_packet_handler(void *arg, int flags, frame::rtp_frame **out);
|
||||
|
||||
/* Encrypt the payload and add authentication tag (if enabled) */
|
||||
static rtp_error_t send_packet_handler(void *arg, buf_vec& buffers);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -170,13 +178,12 @@ namespace uvg_rtp {
|
|||
rtp_error_t create_iv(uint8_t *out, uint32_t ssrc, uint64_t index, uint8_t *salt);
|
||||
|
||||
/* Internal encrypt method that takes only the necessary variables and encrypts "buffer" */
|
||||
rtp_error_t __encrypt(uint32_t ssrc, uint16_t seq, uint8_t *buffer, size_t len);
|
||||
/* rtp_error_t __encrypt(uint32_t ssrc, uint16_t seq, uint8_t *buffer, size_t len); */
|
||||
|
||||
/* Internal init method that initialize the SRTP context using values in key_ctx_.master */
|
||||
rtp_error_t __init(int type, int flags);
|
||||
#endif
|
||||
|
||||
srtp_key_ctx_t key_ctx_;
|
||||
srtp_ctx_t srtp_ctx_;
|
||||
|
||||
/* If NULL cipher is enabled, it means that RTP packets are not
|
||||
|
|
|
@ -14,12 +14,13 @@
|
|||
#include <vector>
|
||||
|
||||
#include "crypto.hh"
|
||||
#include "frame.hh"
|
||||
#include "mzrtp/defines.hh"
|
||||
#include "mzrtp/receiver.hh"
|
||||
|
||||
namespace uvg_rtp {
|
||||
|
||||
enum ROLE {
|
||||
enum ZRTP_ROLE {
|
||||
INITIATOR,
|
||||
RESPONDER
|
||||
};
|
||||
|
@ -183,6 +184,16 @@ namespace uvg_rtp {
|
|||
uint8_t *their_msalt, size_t tsalt_len
|
||||
);
|
||||
|
||||
/* ZRTP packet handler is used after ZRTP state initialization has finished
|
||||
* and media exchange has started. RTP packet dispatcher gives the packet
|
||||
* to "zrtp_handler" which then checks whether the packet is a ZRTP packet
|
||||
* or not and processes it accordingly.
|
||||
*
|
||||
* Return RTP_OK on success
|
||||
* Return RTP_PKT_NOT_HANDLED if "buffer" does not contain a ZRTP message
|
||||
* Return RTP_GENERIC_ERROR if "buffer" contains an invalid ZRTP message */
|
||||
static rtp_error_t packet_handler(ssize_t size, void *packet, int flags, frame::rtp_frame **out);
|
||||
|
||||
private:
|
||||
/* Initialize ZRTP session between us and remote using Diffie-Hellman Mode
|
||||
*
|
||||
|
|
|
@ -249,6 +249,17 @@ void uvg_rtp::crypto::crc32::get_crc32(uint8_t *input, size_t len, uint32_t *out
|
|||
crc32.TruncatedFinal((uint8_t *)output, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
uint32_t uvg_rtp::crypto::crc32::calculate_crc32(uint8_t *input, size_t len)
|
||||
{
|
||||
CryptoPP::CRC32 crc32;
|
||||
uint32_t out;
|
||||
|
||||
crc32.Update(input, len);
|
||||
crc32.TruncatedFinal((uint8_t *)&out, sizeof(uint32_t));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool uvg_rtp::crypto::crc32::verify_crc32(uint8_t *input, size_t len, uint32_t old_crc)
|
||||
{
|
||||
CryptoPP::CRC32 crc32;
|
||||
|
|
|
@ -98,7 +98,7 @@ void uvg_rtp::dispatcher::dispatch_runner(uvg_rtp::dispatcher *dispatcher, uvg_r
|
|||
}
|
||||
|
||||
do {
|
||||
socket->send_vecio(t->headers, t->hdr_ptr, 0);
|
||||
/* socket->send_vecio(t->headers, t->hdr_ptr, 0); */
|
||||
|
||||
if (t->fqueue)
|
||||
t->fqueue->deinit_transaction(t->key);
|
||||
|
|
|
@ -434,7 +434,7 @@ end:
|
|||
}
|
||||
|
||||
uvg_rtp::formats::hevc::hevc(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp, int flags):
|
||||
media(socket, rtp, flags), fqueue_(new uvg_rtp::frame_queue(socket, rtp))
|
||||
media(socket, rtp, flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#define INVALID_SEQ 0xffffffff
|
||||
|
||||
uvg_rtp::formats::media::media(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp_ctx, int flags):
|
||||
socket_(socket), rtp_ctx_(rtp_ctx), flags_(flags)
|
||||
socket_(socket), rtp_ctx_(rtp_ctx), flags_(flags), fqueue_(new uvg_rtp::frame_queue(socket, rtp_ctx, flags))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,42 @@ rtp_error_t uvg_rtp::formats::media::__push_frame(uint8_t *data, size_t data_len
|
|||
{
|
||||
(void)flags;
|
||||
|
||||
rtp_error_t ret;
|
||||
|
||||
if ((ret = fqueue_->init_transaction(data)) != RTP_OK) {
|
||||
LOG_ERROR("Invalid frame queue or failed to initialize transaction!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: Bring back the support for RCE_FRAGMENT_GENERIC
|
||||
* It requires support for modifying the active packet's RTP header,
|
||||
* functionality currently not provided by the frame queue */
|
||||
if (data_len > rtp_ctx_->get_payload_size()) {
|
||||
if (flags_ & RCE_FRAGMENT_GENERIC) {
|
||||
LOG_ERROR("Generic frame fragmentation currently not supported!");
|
||||
return RTP_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
LOG_WARN("Payload is too large and will be truncated (%zu vs %zu)",
|
||||
data_len, rtp_ctx_->get_payload_size()
|
||||
);
|
||||
}
|
||||
|
||||
if ((ret = fqueue_->enqueue_message(data, data_len)) != RTP_OK) {
|
||||
LOG_ERROR("Failed to enqueue message: %d", ret);
|
||||
(void)fqueue_->deinit_transaction();
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = fqueue_->flush_queue()) != RTP_OK) {
|
||||
LOG_ERROR("Failed to flush frame queue: %d", ret);
|
||||
(void)fqueue_->deinit_transaction();
|
||||
return ret;
|
||||
}
|
||||
|
||||
return fqueue_->deinit_transaction();
|
||||
|
||||
#if 0
|
||||
std::vector<std::pair<size_t, uint8_t *>> buffers;
|
||||
size_t payload_size = rtp_ctx_->get_payload_size();
|
||||
uint8_t header[uvg_rtp::frame::HEADER_SIZE_RTP];
|
||||
|
@ -87,9 +123,7 @@ rtp_error_t uvg_rtp::formats::media::__push_frame(uint8_t *data, size_t data_len
|
|||
LOG_WARN("Packet is larger (%zu bytes) than payload_size (%zu bytes)", data_len, payload_size);
|
||||
}
|
||||
}
|
||||
|
||||
rtp_ctx_->inc_sequence();
|
||||
return socket_->sendto(buffers, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::formats::media::packet_handler(void *arg, int flags, uvg_rtp::frame::rtp_frame **out)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
uvg_rtp::media_stream::media_stream(std::string addr, int src_port, int dst_port, rtp_format_t fmt, int flags):
|
||||
srtp_(nullptr),
|
||||
socket_(flags),
|
||||
socket_(nullptr),
|
||||
rtp_(nullptr),
|
||||
rtcp_(nullptr),
|
||||
ctx_config_(),
|
||||
|
@ -53,6 +53,10 @@ uvg_rtp::media_stream::~media_stream()
|
|||
{
|
||||
pkt_dispatcher_->stop();
|
||||
|
||||
if (ctx_config_.flags & RCE_RTCP)
|
||||
rtcp_->stop();
|
||||
|
||||
delete socket_;
|
||||
delete rtcp_;
|
||||
delete rtp_;
|
||||
delete srtp_;
|
||||
|
@ -65,32 +69,35 @@ rtp_error_t uvg_rtp::media_stream::init_connection()
|
|||
{
|
||||
rtp_error_t ret = RTP_OK;
|
||||
|
||||
if ((ret = socket_.init(AF_INET, SOCK_DGRAM, 0)) != RTP_OK)
|
||||
if (!(socket_ = new uvg_rtp::socket(ctx_config_.flags)))
|
||||
return ret;
|
||||
|
||||
if ((ret = socket_->init(AF_INET, SOCK_DGRAM, 0)) != RTP_OK)
|
||||
return ret;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Make the socket non-blocking */
|
||||
int enabled = 1;
|
||||
|
||||
if (::ioctlsocket(socket_.get_raw_socket(), FIONBIO, (u_long *)&enabled) < 0)
|
||||
if (::ioctlsocket(socket_->get_raw_socket(), FIONBIO, (u_long *)&enabled) < 0)
|
||||
LOG_ERROR("Failed to make the socket non-blocking!");
|
||||
#endif
|
||||
|
||||
if (laddr_ != "") {
|
||||
sockaddr_in bind_addr = socket_.create_sockaddr(AF_INET, laddr_, src_port_);
|
||||
socket_t socket = socket_.get_raw_socket();
|
||||
sockaddr_in bind_addr = socket_->create_sockaddr(AF_INET, laddr_, src_port_);
|
||||
socket_t socket = socket_->get_raw_socket();
|
||||
|
||||
if (bind(socket, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) == -1) {
|
||||
log_platform_error("bind(2) failed");
|
||||
return RTP_BIND_ERROR;
|
||||
}
|
||||
} else {
|
||||
if ((ret = socket_.bind(AF_INET, INADDR_ANY, src_port_)) != RTP_OK)
|
||||
if ((ret = socket_->bind(AF_INET, INADDR_ANY, src_port_)) != RTP_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
addr_out_ = socket_.create_sockaddr(AF_INET, addr_, dst_port_);
|
||||
socket_.set_sockaddr(addr_out_);
|
||||
addr_out_ = socket_->create_sockaddr(AF_INET, addr_, dst_port_);
|
||||
socket_->set_sockaddr(addr_out_);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -116,15 +123,14 @@ rtp_error_t uvg_rtp::media_stream::init()
|
|||
return RTP_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
socket_.install_handler(rtcp_, rtcp_->send_packet_handler_buf);
|
||||
socket_.install_handler(rtcp_, rtcp_->send_packet_handler_vec);
|
||||
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);
|
||||
|
||||
switch (fmt_) {
|
||||
case RTP_FORMAT_HEVC:
|
||||
media_ = new uvg_rtp::formats::hevc(&socket_, rtp_, ctx_config_.flags);
|
||||
media_ = new uvg_rtp::formats::hevc(socket_, rtp_, ctx_config_.flags);
|
||||
pkt_dispatcher_->install_aux_handler(
|
||||
rtp_handler_key_,
|
||||
nullptr,
|
||||
|
@ -134,7 +140,7 @@ rtp_error_t uvg_rtp::media_stream::init()
|
|||
|
||||
case RTP_FORMAT_OPUS:
|
||||
case RTP_FORMAT_GENERIC:
|
||||
media_ = new uvg_rtp::formats::media(&socket_, rtp_, ctx_config_.flags);
|
||||
media_ = new uvg_rtp::formats::media(socket_, rtp_, ctx_config_.flags);
|
||||
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, nullptr, media_->packet_handler);
|
||||
break;
|
||||
|
||||
|
@ -154,28 +160,28 @@ rtp_error_t uvg_rtp::media_stream::init()
|
|||
}
|
||||
|
||||
initialized_ = true;
|
||||
return pkt_dispatcher_->start(&socket_, ctx_config_.flags);
|
||||
return pkt_dispatcher_->start(socket_, ctx_config_.flags);
|
||||
}
|
||||
|
||||
#ifdef __RTP_CRYPTO__
|
||||
rtp_error_t uvg_rtp::media_stream::init(uvg_rtp::zrtp *zrtp)
|
||||
{
|
||||
rtp_error_t ret;
|
||||
|
||||
if (init_connection() != RTP_OK) {
|
||||
LOG_ERROR("Failed to initialize the underlying socket: %s!", strerror(errno));
|
||||
return RTP_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
/* First initialize the RTP context for this media stream (SSRC, sequence number, etc.)
|
||||
* Then initialize ZRTP and using ZRTP, initialize SRTP.
|
||||
*
|
||||
* When ZRTP and SRTP have been initialized, create sender and receiver for the media type
|
||||
* before returning the media stream for user */
|
||||
rtp_error_t ret = RTP_OK;
|
||||
|
||||
if ((rtp_ = new uvg_rtp::rtp(fmt_)) == nullptr)
|
||||
if (!(pkt_dispatcher_ = new uvg_rtp::pkt_dispatcher()))
|
||||
return RTP_MEMORY_ERROR;
|
||||
|
||||
if ((ret = zrtp->init(rtp_->get_ssrc(), socket_.get_raw_socket(), addr_out_)) != RTP_OK) {
|
||||
if (!(rtp_ = new uvg_rtp::rtp(fmt_))) {
|
||||
delete pkt_dispatcher_;
|
||||
return RTP_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
if ((ret = zrtp->init(rtp_->get_ssrc(), socket_->get_raw_socket(), addr_out_)) != RTP_OK) {
|
||||
LOG_WARN("Failed to initialize ZRTP for media stream!");
|
||||
return ret;
|
||||
}
|
||||
|
@ -190,20 +196,56 @@ rtp_error_t uvg_rtp::media_stream::init(uvg_rtp::zrtp *zrtp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (!(rtcp_ = new uvg_rtp::rtcp(rtp_))) {
|
||||
delete rtp_;
|
||||
delete pkt_dispatcher_;
|
||||
return RTP_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
socket_->install_handler(rtcp_, rtcp_->send_packet_handler_vec);
|
||||
|
||||
rtp_handler_key_ = pkt_dispatcher_->install_handler(rtp_->packet_handler);
|
||||
zrtp_handler_key_ = pkt_dispatcher_->install_handler(zrtp->packet_handler);
|
||||
|
||||
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, rtcp_, rtcp_->recv_packet_handler);
|
||||
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, srtp_, srtp_->recv_packet_handler);
|
||||
|
||||
switch (fmt_) {
|
||||
case RTP_FORMAT_HEVC:
|
||||
media_ = new uvg_rtp::formats::hevc(socket_, rtp_, ctx_config_.flags);
|
||||
pkt_dispatcher_->install_aux_handler(
|
||||
rtp_handler_key_,
|
||||
nullptr,
|
||||
dynamic_cast<uvg_rtp::formats::hevc *>(media_)->packet_handler
|
||||
);
|
||||
break;
|
||||
|
||||
case RTP_FORMAT_OPUS:
|
||||
case RTP_FORMAT_GENERIC:
|
||||
media_ = new uvg_rtp::formats::media(socket_, rtp_, ctx_config_.flags);
|
||||
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, nullptr, media_->packet_handler);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERROR("Unknown payload format %u\n", fmt_);
|
||||
}
|
||||
|
||||
if (!media_) {
|
||||
delete rtp_;
|
||||
delete pkt_dispatcher_;
|
||||
return RTP_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
if (ctx_config_.flags & RCE_RTCP) {
|
||||
rtcp_->add_participant(addr_, src_port_ + 1, dst_port_ + 1, rtp_->get_clock_rate());
|
||||
rtcp_->start();
|
||||
}
|
||||
|
||||
if (ctx_config_.flags & RCE_SRTP_AUTHENTICATE_RTP)
|
||||
rtp_->set_payload_size(MAX_PAYLOAD - AUTH_TAG_LENGTH);
|
||||
|
||||
socket_.set_srtp(srtp_);
|
||||
|
||||
/* TODO: install srtp packet handler */
|
||||
|
||||
receiver_ = new uvg_rtp::receiver(socket_, ctx_config_, fmt_, rtp_);
|
||||
|
||||
receiver_->start();
|
||||
|
||||
initialized_ = true;
|
||||
|
||||
return ret;
|
||||
return pkt_dispatcher_->start(socket_, ctx_config_.flags);
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
|
||||
|
@ -217,14 +259,14 @@ rtp_error_t uvg_rtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
|
|||
if ((flags_ & srtp_flags) != srtp_flags)
|
||||
return RTP_NOT_SUPPORTED;
|
||||
|
||||
if (init_connection() != RTP_OK) {
|
||||
LOG_ERROR("Failed to initialize the underlying socket: %s!", strerror(errno));
|
||||
return RTP_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
if ((rtp_ = new uvg_rtp::rtp(fmt_)) == nullptr)
|
||||
if (!(pkt_dispatcher_ = new uvg_rtp::pkt_dispatcher()))
|
||||
return RTP_MEMORY_ERROR;
|
||||
|
||||
if (!(rtp_ = new uvg_rtp::rtp(fmt_))) {
|
||||
delete pkt_dispatcher_;
|
||||
return RTP_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
if ((srtp_ = new uvg_rtp::srtp()) == nullptr)
|
||||
return RTP_MEMORY_ERROR;
|
||||
|
||||
|
@ -233,18 +275,56 @@ rtp_error_t uvg_rtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (!(rtcp_ = new uvg_rtp::rtcp(rtp_))) {
|
||||
delete rtp_;
|
||||
delete pkt_dispatcher_;
|
||||
return RTP_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
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);
|
||||
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, srtp_, srtp_->recv_packet_handler);
|
||||
|
||||
switch (fmt_) {
|
||||
case RTP_FORMAT_HEVC:
|
||||
media_ = new uvg_rtp::formats::hevc(socket_, rtp_, ctx_config_.flags);
|
||||
pkt_dispatcher_->install_aux_handler(
|
||||
rtp_handler_key_,
|
||||
nullptr,
|
||||
dynamic_cast<uvg_rtp::formats::hevc *>(media_)->packet_handler
|
||||
);
|
||||
break;
|
||||
|
||||
case RTP_FORMAT_OPUS:
|
||||
case RTP_FORMAT_GENERIC:
|
||||
media_ = new uvg_rtp::formats::media(socket_, rtp_, ctx_config_.flags);
|
||||
pkt_dispatcher_->install_aux_handler(rtp_handler_key_, nullptr, media_->packet_handler);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERROR("Unknown payload format %u\n", fmt_);
|
||||
}
|
||||
|
||||
if (!media_) {
|
||||
delete rtp_;
|
||||
delete pkt_dispatcher_;
|
||||
return RTP_MEMORY_ERROR;
|
||||
}
|
||||
|
||||
if (ctx_config_.flags & RCE_RTCP) {
|
||||
rtcp_->add_participant(addr_, src_port_ + 1, dst_port_ + 1, rtp_->get_clock_rate());
|
||||
rtcp_->start();
|
||||
}
|
||||
|
||||
if (ctx_config_.flags & RCE_SRTP_AUTHENTICATE_RTP)
|
||||
rtp_->set_payload_size(MAX_PAYLOAD - AUTH_TAG_LENGTH);
|
||||
|
||||
socket_.set_srtp(srtp_);
|
||||
|
||||
receiver_ = new uvg_rtp::receiver(socket_, ctx_config_, fmt_, rtp_);
|
||||
|
||||
receiver_->start();
|
||||
|
||||
initialized_ = true;
|
||||
return pkt_dispatcher_->start(socket_, ctx_config_.flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -394,7 +474,7 @@ rtp_error_t uvg_rtp::media_stream::configure_ctx(int flag, ssize_t value)
|
|||
return RTP_INVALID_VALUE;
|
||||
|
||||
int buf_size = value;
|
||||
if ((ret = socket_.setsockopt(SOL_SOCKET, SO_SNDBUF, (const char *)&buf_size, sizeof(int))) != RTP_OK)
|
||||
if ((ret = socket_->setsockopt(SOL_SOCKET, SO_SNDBUF, (const char *)&buf_size, sizeof(int))) != RTP_OK)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
@ -404,7 +484,7 @@ rtp_error_t uvg_rtp::media_stream::configure_ctx(int flag, ssize_t value)
|
|||
return RTP_INVALID_VALUE;
|
||||
|
||||
int buf_size = value;
|
||||
if ((ret = socket_.setsockopt(SOL_SOCKET, SO_RCVBUF, (const char *)&buf_size, sizeof(int))) != RTP_OK)
|
||||
if ((ret = socket_->setsockopt(SOL_SOCKET, SO_RCVBUF, (const char *)&buf_size, sizeof(int))) != RTP_OK)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -62,7 +62,7 @@ uvg_rtp::zrtp_msg::commit::commit(zrtp_session_t& session)
|
|||
memcpy(&msg->mac, mac_full, sizeof(uint64_t));
|
||||
|
||||
/* Calculate CRC32 for the whole ZRTP packet */
|
||||
uvg_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
msg->crc = uvg_rtp::crypto::crc32::calculate_crc32((uint8_t *)frame_, len_ - sizeof(uint32_t));
|
||||
|
||||
/* Finally make a copy of the message and save it for later use */
|
||||
session.l_msg.commit.first = len_;
|
||||
|
|
|
@ -38,7 +38,7 @@ uvg_rtp::zrtp_msg::confack::confack(zrtp_session_t& session)
|
|||
memcpy(&msg->msg_start.msgblock, ZRTP_CONFACK, 8);
|
||||
|
||||
/* Calculate CRC32 for the whole ZRTP packet */
|
||||
uvg_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
msg->crc = uvg_rtp::crypto::crc32::calculate_crc32((uint8_t *)frame_, len_ - sizeof(uint32_t));
|
||||
}
|
||||
|
||||
uvg_rtp::zrtp_msg::confack::~confack()
|
||||
|
|
|
@ -73,7 +73,7 @@ uvg_rtp::zrtp_msg::confirm::confirm(zrtp_session_t& session, int part)
|
|||
memcpy(&msg->confirm_mac, mac_full, sizeof(uint64_t));
|
||||
|
||||
/* Calculate CRC32 for the whole ZRTP packet */
|
||||
uvg_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
msg->crc = uvg_rtp::crypto::crc32::calculate_crc32((uint8_t *)frame_, len_ - sizeof(uint32_t));
|
||||
|
||||
delete hmac_sha256;
|
||||
delete aes_cfb;
|
||||
|
|
|
@ -87,7 +87,7 @@ uvg_rtp::zrtp_msg::dh_key_exchange::dh_key_exchange(zrtp_session_t& session, int
|
|||
memcpy(msg->mac, mac_full, 8);
|
||||
|
||||
/* Calculate CRC32 for the whole ZRTP packet */
|
||||
uvg_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
msg->crc = uvg_rtp::crypto::crc32::calculate_crc32((uint8_t *)frame_, len_ - sizeof(uint32_t));
|
||||
|
||||
/* Finally make a copy of the message and save it for later use */
|
||||
if (session.l_msg.dh.second)
|
||||
|
|
|
@ -27,7 +27,7 @@ uvg_rtp::zrtp_msg::error::error(int error_code)
|
|||
|
||||
msg->error = error_code;
|
||||
|
||||
uvg_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
msg->crc = uvg_rtp::crypto::crc32::calculate_crc32((uint8_t *)frame_, len_ - sizeof(uint32_t));
|
||||
}
|
||||
|
||||
uvg_rtp::zrtp_msg::error::~error()
|
||||
|
|
|
@ -66,7 +66,7 @@ uvg_rtp::zrtp_msg::hello::hello(zrtp_session_t& session)
|
|||
memcpy(&msg->mac, mac_full, sizeof(uint64_t));
|
||||
|
||||
/* Calculate CRC32 of the whole packet (excluding crc) */
|
||||
uvg_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
msg->crc = uvg_rtp::crypto::crc32::calculate_crc32((uint8_t *)frame_, len_ - sizeof(uint32_t));
|
||||
|
||||
/* Finally make a copy of the message and save it for later use */
|
||||
session.l_msg.hello.first = len_;
|
||||
|
|
|
@ -25,7 +25,7 @@ uvg_rtp::zrtp_msg::hello_ack::hello_ack()
|
|||
|
||||
memcpy(&msg->msg_start.msgblock, ZRTP_HELLO_ACK, 8);
|
||||
|
||||
uvg_rtp::crypto::crc32::get_crc32((uint8_t *)frame_, len_ - 4, &msg->crc);
|
||||
msg->crc = uvg_rtp::crypto::crc32::calculate_crc32((uint8_t *)frame_, len_ - sizeof(uint32_t));
|
||||
}
|
||||
|
||||
uvg_rtp::zrtp_msg::hello_ack::~hello_ack()
|
||||
|
|
|
@ -25,25 +25,6 @@
|
|||
|
||||
using namespace uvg_rtp::zrtp_msg;
|
||||
|
||||
enum MSG_TYPES {
|
||||
ZRTP_MSG_HELLO = 0x2020206f6c6c6548,
|
||||
ZRTP_MSG_HELLO_ACK = 0x4b43416f6c6c6548,
|
||||
ZRTP_MSG_COMMIT = 0x202074696d6d6f43,
|
||||
ZRTP_MSG_DH_PART1 = 0x2031747261504844,
|
||||
ZRTP_MSG_DH_PART2 = 0x2032747261504844,
|
||||
ZRTP_MSG_CONFIRM1 = 0x316d7269666e6f43,
|
||||
ZRTP_MSG_CONFIRM2 = 0x326d7269666e6f43,
|
||||
ZRTP_MSG_CONF2_ACK = 0x4b434132666e6f43,
|
||||
ZRTP_MSG_ERROR = 0x202020726f727245,
|
||||
ZRTP_MSG_ERROR_ACK = 0x4b4341726f727245,
|
||||
ZRTP_MSG_GO_CLEAR = 0x207261656c436f47,
|
||||
ZRTP_MSG_CLEAR_ACK = 0x4b43417261656c43,
|
||||
ZRTP_MSG_SAS_RELAY = 0x79616c6572534153,
|
||||
ZRTP_MSG_RELAY_ACK = 0x4b434179616c6552,
|
||||
ZRTP_MSG_PING = 0x20202020676e6950,
|
||||
ZRTP_MSG_PING_ACK = 0x204b4341676e6950,
|
||||
};
|
||||
|
||||
uvg_rtp::zrtp_msg::receiver::receiver()
|
||||
{
|
||||
mem_ = new uint8_t[1024];
|
||||
|
@ -217,46 +198,4 @@ ssize_t uvg_rtp::zrtp_msg::receiver::get_msg(void *ptr, size_t len)
|
|||
return rlen_;
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::zrtp_msg::receiver::zrtp_handler(ssize_t size, void *buffer)
|
||||
{
|
||||
zrtp_msg *msg = (zrtp_msg *)buffer;
|
||||
|
||||
/* not a ZRTP packet */
|
||||
if (msg->header.version || msg->header.magic != ZRTP_HEADER_MAGIC || msg->magic != ZRTP_MSG_MAGIC)
|
||||
return RTP_PKT_NOT_HANDLED;
|
||||
|
||||
switch (msg->msgblock) {
|
||||
/* None of these messages should be received by this stream
|
||||
* during this stage so return RTP_GENERIC_ERROR to indicate that the packet
|
||||
* is invalid and that it should not be dispatched to other packet handlers */
|
||||
case ZRTP_MSG_HELLO:
|
||||
case ZRTP_MSG_HELLO_ACK:
|
||||
case ZRTP_MSG_COMMIT:
|
||||
case ZRTP_MSG_DH_PART1:
|
||||
case ZRTP_MSG_DH_PART2:
|
||||
case ZRTP_MSG_CONFIRM1:
|
||||
case ZRTP_MSG_CONFIRM2:
|
||||
case ZRTP_MSG_CONF2_ACK:
|
||||
return RTP_GENERIC_ERROR;
|
||||
|
||||
case ZRTP_MSG_ERROR:
|
||||
/* TODO: */
|
||||
return RTP_OK;
|
||||
|
||||
case ZRTP_MSG_ERROR_ACK:
|
||||
/* TODO: */
|
||||
return RTP_OK;
|
||||
|
||||
case ZRTP_MSG_SAS_RELAY:
|
||||
return RTP_OK;
|
||||
|
||||
case ZRTP_MSG_RELAY_ACK:
|
||||
return RTP_OK;
|
||||
|
||||
case ZRTP_MSG_PING_ACK:
|
||||
return RTP_OK;
|
||||
|
||||
/* TODO: goclear & co-opeartion with srtp */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
130
src/queue.cc
130
src/queue.cc
|
@ -14,25 +14,8 @@
|
|||
|
||||
#include "formats/hevc.hh"
|
||||
|
||||
/* uvg_rtp::frame_queue::frame_queue(rtp_format_t fmt): */
|
||||
/* active_(nullptr), fmt_(fmt), dealloc_hook_(nullptr) */
|
||||
/* { */
|
||||
/* active_ = nullptr; */
|
||||
/* dispatcher_ = nullptr; */
|
||||
|
||||
/* max_queued_ = MAX_QUEUED_MSGS; */
|
||||
/* max_mcount_ = MAX_MSG_COUNT; */
|
||||
/* max_ccount_ = MAX_CHUNK_COUNT * max_mcount_; */
|
||||
/* } */
|
||||
|
||||
/* uvg_rtp::frame_queue::frame_queue(rtp_format_t fmt, uvg_rtp::dispatcher *dispatcher): */
|
||||
/* frame_queue(fmt) */
|
||||
/* { */
|
||||
/* dispatcher_ = dispatcher; */
|
||||
/* } */
|
||||
|
||||
uvg_rtp::frame_queue::frame_queue(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp):
|
||||
rtp_(rtp), socket_(socket)
|
||||
uvg_rtp::frame_queue::frame_queue(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp, int flags):
|
||||
rtp_(rtp), socket_(socket), flags_(flags)
|
||||
{
|
||||
active_ = nullptr;
|
||||
dispatcher_ = nullptr;
|
||||
|
@ -86,15 +69,21 @@ rtp_error_t uvg_rtp::frame_queue::init_transaction()
|
|||
free_.pop_back();
|
||||
}
|
||||
|
||||
active_->chunk_ptr = 0;
|
||||
active_->hdr_ptr = 0;
|
||||
active_->rtphdr_ptr = 0;
|
||||
active_->fqueue = this;
|
||||
active_->chunk_ptr = 0;
|
||||
active_->hdr_ptr = 0;
|
||||
active_->rtphdr_ptr = 0;
|
||||
active_->rtpauth_ptr = 0;
|
||||
active_->fqueue = this;
|
||||
|
||||
active_->data_raw = nullptr;
|
||||
active_->data_smart = nullptr;
|
||||
active_->dealloc_hook = dealloc_hook_;
|
||||
|
||||
if (flags_ & RCE_SRTP_AUTHENTICATE_RTP)
|
||||
active_->rtp_auth_tags = new uint64_t[max_mcount_];
|
||||
else
|
||||
active_->rtp_auth_tags = nullptr;
|
||||
|
||||
active_->out_addr = socket_->get_out_address();
|
||||
rtp_->fill_header((uint8_t *)&active_->rtp_common);
|
||||
active_->buffers.clear();
|
||||
|
@ -142,6 +131,7 @@ rtp_error_t uvg_rtp::frame_queue::destroy_transaction(uvg_rtp::transaction_t *t)
|
|||
delete[] t->headers;
|
||||
delete[] t->chunks;
|
||||
delete[] t->rtp_headers;
|
||||
delete[] t->rtp_auth_tags;
|
||||
|
||||
t->headers = nullptr;
|
||||
t->chunks = nullptr;
|
||||
|
@ -202,6 +192,7 @@ rtp_error_t uvg_rtp::frame_queue::deinit_transaction(uint32_t key)
|
|||
break;
|
||||
}
|
||||
|
||||
delete[] transaction_it->second->rtp_auth_tags;
|
||||
delete[] transaction_it->second->headers;
|
||||
delete[] transaction_it->second->chunks;
|
||||
delete[] transaction_it->second->rtp_headers;
|
||||
|
@ -229,35 +220,28 @@ rtp_error_t uvg_rtp::frame_queue::enqueue_message(uint8_t *message, size_t messa
|
|||
if (!message || !message_len)
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
#ifdef __linux__
|
||||
if (active_->chunk_ptr + 2 >= (size_t)max_ccount_ || active_->hdr_ptr + 1 >= (size_t)max_mcount_) {
|
||||
LOG_ERROR("maximum amount of chunks (%zu) or messages (%zu) exceeded!", active_->chunk_ptr, active_->hdr_ptr);
|
||||
return RTP_MEMORY_ERROR;
|
||||
}
|
||||
/* Create buffer vector where the full packet is constructed
|
||||
* and which is then pushed to "active_"'s pkt_vec structure */
|
||||
uvg_rtp::buf_vec tmp;
|
||||
|
||||
/* update the RTP header at "rtpheaders_ptr_" */
|
||||
uvg_rtp::frame_queue::update_rtp_header();
|
||||
|
||||
active_->chunks[active_->chunk_ptr + 0].iov_base = &active_->rtp_headers[active_->rtphdr_ptr];
|
||||
active_->chunks[active_->chunk_ptr + 0].iov_len = sizeof(active_->rtp_headers[active_->rtphdr_ptr]);
|
||||
/* Push RTP header first and then push all payload buffers */
|
||||
tmp.push_back({
|
||||
sizeof(active_->rtp_headers[active_->rtphdr_ptr]),
|
||||
(uint8_t *)&active_->rtp_headers[active_->rtphdr_ptr++]
|
||||
});
|
||||
|
||||
active_->chunks[active_->chunk_ptr + 1].iov_base = message;
|
||||
active_->chunks[active_->chunk_ptr + 1].iov_len = message_len;
|
||||
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_name = (void *)&active_->out_addr;
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_namelen = sizeof(active_->out_addr);
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_iov = &active_->chunks[active_->chunk_ptr];
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_iovlen = 2;
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_control = 0;
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_controllen = 0;
|
||||
|
||||
active_->rtphdr_ptr += 1;
|
||||
active_->chunk_ptr += 2;
|
||||
active_->hdr_ptr += 1;
|
||||
#else
|
||||
/* TODO: winsock stuff */
|
||||
#endif
|
||||
if (flags_ & RCE_SRTP_AUTHENTICATE_RTP) {
|
||||
tmp.push_back({
|
||||
sizeof(uint64_t),
|
||||
(uint8_t *)&active_->rtp_auth_tags[active_->rtpauth_ptr++]
|
||||
});
|
||||
}
|
||||
|
||||
tmp.push_back({ message_len, message });
|
||||
active_->packets.push_back(tmp);
|
||||
rtp_->inc_sequence();
|
||||
rtp_->inc_sent_pkts();
|
||||
|
||||
|
@ -269,37 +253,30 @@ rtp_error_t uvg_rtp::frame_queue::enqueue_message(std::vector<std::pair<size_t,
|
|||
if (!buffers.size())
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
#ifdef __linux__
|
||||
if (active_->chunk_ptr + buffers.size() + 1 >= (size_t)max_ccount_ || active_->hdr_ptr + 1 >= (size_t)max_mcount_) {
|
||||
LOG_ERROR("maximum amount of chunks (%zu) or messages (%zu) exceeded!", active_->chunk_ptr, active_->hdr_ptr);
|
||||
return RTP_MEMORY_ERROR;
|
||||
}
|
||||
/* Create buffer vector where the full packet is constructed
|
||||
* and which is then pushed to "active_"'s pkt_vec structure */
|
||||
uvg_rtp::buf_vec tmp;
|
||||
|
||||
/* update the RTP header at "rtpheaders_ptr_" */
|
||||
uvg_rtp::frame_queue::update_rtp_header();
|
||||
|
||||
active_->chunks[active_->chunk_ptr].iov_len = sizeof(active_->rtp_headers[active_->rtphdr_ptr]);
|
||||
active_->chunks[active_->chunk_ptr].iov_base = &active_->rtp_headers[active_->rtphdr_ptr];
|
||||
/* Push RTP header first and then push all payload buffers */
|
||||
tmp.push_back({
|
||||
sizeof(active_->rtp_headers[active_->rtphdr_ptr]),
|
||||
(uint8_t *)&active_->rtp_headers[active_->rtphdr_ptr++]
|
||||
});
|
||||
|
||||
for (size_t i = 0; i < buffers.size(); ++i) {
|
||||
active_->chunks[active_->chunk_ptr + i + 1].iov_len = buffers.at(i).first;
|
||||
active_->chunks[active_->chunk_ptr + i + 1].iov_base = buffers.at(i).second;
|
||||
for (size_t i = 0; i < buffers.size(); ++i)
|
||||
tmp.push_back({ buffers.at(i).first, buffers.at(i).second });
|
||||
|
||||
if (flags_ & RCE_SRTP_AUTHENTICATE_RTP) {
|
||||
tmp.push_back({
|
||||
sizeof(uint64_t),
|
||||
(uint8_t *)&active_->rtp_auth_tags[active_->rtpauth_ptr++]
|
||||
});
|
||||
}
|
||||
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_name = (void *)&active_->out_addr;
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_namelen = sizeof(active_->out_addr);
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_iov = &active_->chunks[active_->chunk_ptr];
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_iovlen = buffers.size() + 1;
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_control = 0;
|
||||
active_->headers[active_->hdr_ptr].msg_hdr.msg_controllen = 0;
|
||||
|
||||
active_->chunk_ptr += buffers.size() + 1;
|
||||
active_->hdr_ptr += 1;
|
||||
active_->rtphdr_ptr += 1;
|
||||
#else
|
||||
/* TODO: winsock stuff */
|
||||
#endif
|
||||
|
||||
active_->packets.push_back(tmp);
|
||||
rtp_->inc_sequence();
|
||||
rtp_->inc_sent_pkts();
|
||||
|
||||
|
@ -317,27 +294,18 @@ rtp_error_t uvg_rtp::frame_queue::flush_queue()
|
|||
/* set the marker bit of the last packet to 1 */
|
||||
((uint8_t *)&active_->rtp_headers[active_->rtphdr_ptr - 1])[1] |= (1 << 7);
|
||||
|
||||
#ifdef __linux__
|
||||
transaction_mtx_.lock();
|
||||
queued_.insert(std::make_pair(active_->key, active_));
|
||||
transaction_mtx_.unlock();
|
||||
|
||||
if (dispatcher_) {
|
||||
dispatcher_->trigger_send(active_);
|
||||
active_ = nullptr;
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
if (socket_->send_vecio(active_->headers, active_->hdr_ptr, 0) != RTP_OK) {
|
||||
if (socket_->sendto(active_->packets, 0) != RTP_OK) {
|
||||
LOG_ERROR("Failed to flush the message queue: %s", strerror(errno));
|
||||
(void)deinit_transaction();
|
||||
return RTP_SEND_ERROR;
|
||||
}
|
||||
|
||||
LOG_DEBUG("full message took %zu chunks and %zu messages", active_->chunk_ptr, active_->hdr_ptr);
|
||||
|
||||
return deinit_transaction();
|
||||
#endif
|
||||
}
|
||||
|
||||
void uvg_rtp::frame_queue::update_rtp_header()
|
||||
|
@ -346,7 +314,7 @@ void uvg_rtp::frame_queue::update_rtp_header()
|
|||
rtp_->update_sequence((uint8_t *)(&active_->rtp_headers[active_->rtphdr_ptr]));
|
||||
}
|
||||
|
||||
uvg_rtp::buff_vec& uvg_rtp::frame_queue::get_buffer_vector()
|
||||
uvg_rtp::buf_vec& uvg_rtp::frame_queue::get_buffer_vector()
|
||||
{
|
||||
return active_->buffers;
|
||||
}
|
||||
|
|
|
@ -438,12 +438,7 @@ rtp_error_t uvg_rtp::rtcp::recv_packet_handler(void *arg, int flags, frame::rtp_
|
|||
return RTP_PKT_NOT_HANDLED;
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::rtcp::send_packet_handler_buf(void *arg, ssize_t len, void *buf)
|
||||
{
|
||||
return ((uvg_rtp::rtcp *)arg)->update_sender_stats(len - uvg_rtp::frame::HEADER_SIZE_RTP);
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::rtcp::send_packet_handler_vec(void *arg, std::vector<std::pair<size_t, uint8_t *>>& buffers)
|
||||
rtp_error_t uvg_rtp::rtcp::send_packet_handler_vec(void *arg, uvg_rtp::buf_vec& buffers)
|
||||
{
|
||||
ssize_t pkt_size = -uvg_rtp::frame::HEADER_SIZE_RTP;
|
||||
|
||||
|
|
258
src/socket.cc
258
src/socket.cc
|
@ -23,7 +23,6 @@ using namespace mingw;
|
|||
|
||||
uvg_rtp::socket::socket(int flags):
|
||||
socket_(-1),
|
||||
srtp_(nullptr),
|
||||
flags_(flags)
|
||||
{
|
||||
}
|
||||
|
@ -125,31 +124,12 @@ void uvg_rtp::socket::set_sockaddr(sockaddr_in addr)
|
|||
addr_ = addr;
|
||||
}
|
||||
|
||||
void uvg_rtp::socket::set_srtp(uvg_rtp::srtp *srtp)
|
||||
{
|
||||
srtp_ = srtp;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -159,7 +139,7 @@ rtp_error_t uvg_rtp::socket::install_handler(void *arg, packet_handler_vec handl
|
|||
socket_packet_handler hndlr;
|
||||
|
||||
hndlr.arg = arg;
|
||||
hndlr.handlers.vec = handler;
|
||||
hndlr.handler = handler;
|
||||
vec_handlers_.push_back(hndlr);
|
||||
|
||||
return RTP_OK;
|
||||
|
@ -202,80 +182,33 @@ 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);
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::socket::__sendtov(
|
||||
sockaddr_in& addr,
|
||||
std::vector<std::pair<size_t, uint8_t *>> buffers,
|
||||
uvg_rtp::buf_vec& buffers,
|
||||
int flags, int *bytes_sent
|
||||
)
|
||||
{
|
||||
#ifdef __linux__
|
||||
int sent_bytes = 0;
|
||||
|
||||
#ifdef __RTP_CRYPTO__
|
||||
if (srtp_) {
|
||||
auto ret = srtp_->encrypt(buffers);
|
||||
|
||||
if (ret != RTP_OK) {
|
||||
LOG_ERROR("Failed to encrypt RTP packet!");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < buffers.size(); ++i) {
|
||||
chunks_[i].iov_len = buffers.at(i).first;
|
||||
chunks_[i].iov_base = buffers.at(i).second;
|
||||
|
@ -325,12 +258,12 @@ rtp_error_t uvg_rtp::socket::__sendtov(
|
|||
#endif
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::socket::sendto(std::vector<std::pair<size_t, uint8_t *>> buffers, int flags)
|
||||
rtp_error_t uvg_rtp::socket::sendto(buf_vec& buffers, int flags)
|
||||
{
|
||||
rtp_error_t ret;
|
||||
|
||||
for (auto& handler : buf_handlers_) {
|
||||
if ((ret = (*handler.handlers.vec)(handler.arg, buffers)) != RTP_OK) {
|
||||
if ((ret = (*handler.handler)(handler.arg, buffers)) != RTP_OK) {
|
||||
LOG_ERROR("Malfored packet");
|
||||
return ret;
|
||||
}
|
||||
|
@ -339,12 +272,12 @@ rtp_error_t uvg_rtp::socket::sendto(std::vector<std::pair<size_t, uint8_t *>> bu
|
|||
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 uvg_rtp::socket::sendto(buf_vec& 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) {
|
||||
if ((ret = (*handler.handler)(handler.arg, buffers)) != RTP_OK) {
|
||||
LOG_ERROR("Malfored packet");
|
||||
return ret;
|
||||
}
|
||||
|
@ -353,12 +286,12 @@ rtp_error_t uvg_rtp::socket::sendto(std::vector<std::pair<size_t, uint8_t *>> bu
|
|||
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 uvg_rtp::socket::sendto(sockaddr_in& addr, buf_vec& buffers, int flags)
|
||||
{
|
||||
rtp_error_t ret;
|
||||
|
||||
for (auto& handler : buf_handlers_) {
|
||||
if ((ret = (*handler.handlers.vec)(handler.arg, buffers)) != RTP_OK) {
|
||||
if ((ret = (*handler.handler)(handler.arg, buffers)) != RTP_OK) {
|
||||
LOG_ERROR("Malfored packet");
|
||||
return ret;
|
||||
}
|
||||
|
@ -369,80 +302,164 @@ rtp_error_t uvg_rtp::socket::sendto(sockaddr_in& addr, std::vector<std::pair<siz
|
|||
|
||||
rtp_error_t uvg_rtp::socket::sendto(
|
||||
sockaddr_in& addr,
|
||||
std::vector<std::pair<size_t, uint8_t *>> buffers,
|
||||
buf_vec& 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) {
|
||||
if ((ret = (*handler.handler)(handler.arg, buffers)) != RTP_OK) {
|
||||
LOG_ERROR("Malfored packet");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
auto buf = { buffers };
|
||||
return __sendtov(addr, buffers, flags, bytes_sent);
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::socket::send_vecio(vecio_buf *buffers, size_t nbuffers, int flags)
|
||||
rtp_error_t uvg_rtp::socket::__sendtov(
|
||||
sockaddr_in& addr,
|
||||
uvg_rtp::pkt_vec& buffers,
|
||||
int flags, int *bytes_sent
|
||||
)
|
||||
{
|
||||
if (buffers == nullptr || nbuffers == 0)
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
#ifdef __linux__
|
||||
size_t npkts = (flags_ & RCE_NO_SYSTEM_CALL_CLUSTERING) ? 1 : 1024;
|
||||
int sent_bytes = 0;
|
||||
|
||||
while (nbuffers > npkts) {
|
||||
if (sendmmsg(socket_, buffers, npkts, flags) < 0) {
|
||||
LOG_ERROR("Failed to flush the message queue: %s", strerror(errno));
|
||||
return RTP_SEND_ERROR;
|
||||
struct mmsghdr *headers = new struct mmsghdr[buffers.size()];
|
||||
|
||||
for (size_t i = 0; i < buffers.size(); ++i) {
|
||||
headers[i].msg_hdr.msg_iov = new struct iovec[buffers[i].size()];
|
||||
headers[i].msg_hdr.msg_iovlen = buffers[i].size();
|
||||
headers[i].msg_hdr.msg_name = (void *)&addr;
|
||||
headers[i].msg_hdr.msg_namelen = sizeof(addr);
|
||||
headers[i].msg_hdr.msg_control = 0;
|
||||
headers[i].msg_hdr.msg_controllen = 0;
|
||||
|
||||
for (size_t k = 0; k < buffers[i].size(); ++k) {
|
||||
for (auto& buf : buffers[i]) {
|
||||
headers[i].msg_hdr.msg_iov[k].iov_len = buf.first;
|
||||
headers[i].msg_hdr.msg_iov[k].iov_base = buf.second;
|
||||
|
||||
sent_bytes += buf.first;
|
||||
}
|
||||
}
|
||||
|
||||
nbuffers -= npkts;
|
||||
buffers += npkts;
|
||||
}
|
||||
|
||||
if (sendmmsg(socket_, buffers, nbuffers, flags) < 0) {
|
||||
LOG_ERROR("Failed to flush the message queue: %s", strerror(errno));
|
||||
/* TODO: RCE_NO_SYSTEM_CALL_CLUSTERING */
|
||||
|
||||
if (sendmmsg(socket_, headers, buffers.size(), flags) < 0) {
|
||||
LOG_ERROR("Failed to send RTP frame: %s!", strerror(errno));
|
||||
set_bytes(bytes_sent, -1);
|
||||
return RTP_SEND_ERROR;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < buffers.size(); ++i)
|
||||
delete[] headers[i].msg_hdr.msg_iov;
|
||||
delete[] headers;
|
||||
|
||||
set_bytes(bytes_sent, sent_bytes);
|
||||
return RTP_OK;
|
||||
|
||||
#else
|
||||
/* TODO: */
|
||||
INT sent_bytes, ret;
|
||||
WSABUF wsa_bufs[16];
|
||||
|
||||
for (auto& buffer : buffers) {
|
||||
/* create WSABUFs from input buffer and send them at once */
|
||||
for (size_t i = 0; i < buffer.size(); ++i) {
|
||||
wsa_bufs[i].len = buffer.at(i).first;
|
||||
wsa_bufs[i].buf = buffer.at(i).second;
|
||||
}
|
||||
|
||||
ret = WSASendTo(
|
||||
socket_,
|
||||
wsa_bufs,
|
||||
buffers.size(),
|
||||
&sent_bytes,
|
||||
flags,
|
||||
(SOCKADDR *)&addr,
|
||||
sizeof(addr_),
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
|
||||
if (ret == -1) {
|
||||
log_platform_error("WSASendTo() failed");
|
||||
set_bytes(bytes_sent, -1);
|
||||
return RTP_SEND_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
set_bytes(bytes_sent, sent_bytes);
|
||||
return RTP_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::socket::recv_vecio(vecio_buf *buffers, size_t nbuffers, int flags, int *nread)
|
||||
rtp_error_t uvg_rtp::socket::sendto(pkt_vec& buffers, int flags)
|
||||
{
|
||||
if (buffers == nullptr || nbuffers == 0)
|
||||
return RTP_INVALID_VALUE;
|
||||
rtp_error_t ret;
|
||||
|
||||
ssize_t dgrams_read = 0;
|
||||
|
||||
#ifdef __linux__
|
||||
if (flags_ & RCE_NO_SYSTEM_CALL_CLUSTERING) {
|
||||
for (size_t i = 0; i < nbuffers; ++i) {
|
||||
if ((dgrams_read += ::recvmmsg(socket_, &buffers[i], 1, flags, nullptr)) < 0) {
|
||||
LOG_ERROR("recvmmsg(2) failed: %s", strerror(errno));
|
||||
set_bytes(nread, -1);
|
||||
return RTP_GENERIC_ERROR;
|
||||
for (auto& buffer : buffers) {
|
||||
for (auto& handler : buf_handlers_) {
|
||||
if ((ret = (*handler.handler)(handler.arg, buffer)) != RTP_OK) {
|
||||
LOG_ERROR("Malfored packet");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((dgrams_read = ::recvmmsg(socket_, buffers, nbuffers, flags, nullptr)) < 0) {
|
||||
LOG_ERROR("recvmmsg(2) failed: %s", strerror(errno));
|
||||
set_bytes(nread, -1);
|
||||
return RTP_GENERIC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
set_bytes(nread, dgrams_read);
|
||||
return RTP_OK;
|
||||
#else
|
||||
/* TODO: */
|
||||
#endif
|
||||
return __sendtov(addr_, buffers, flags, nullptr);
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::socket::sendto(pkt_vec& buffers, int flags, int *bytes_sent)
|
||||
{
|
||||
rtp_error_t ret;
|
||||
|
||||
for (auto& buffer : buffers) {
|
||||
for (auto& handler : buf_handlers_) {
|
||||
if ((ret = (*handler.handler)(handler.arg, buffer)) != 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, pkt_vec& buffers, int flags)
|
||||
{
|
||||
rtp_error_t ret;
|
||||
|
||||
for (auto& buffer : buffers) {
|
||||
for (auto& handler : buf_handlers_) {
|
||||
if ((ret = (*handler.handler)(handler.arg, buffer)) != RTP_OK) {
|
||||
LOG_ERROR("Malfored packet");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return __sendtov(addr, buffers, flags, nullptr);
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::socket::sendto(sockaddr_in& addr, pkt_vec& buffers, int flags, int *bytes_sent)
|
||||
{
|
||||
rtp_error_t ret;
|
||||
|
||||
for (auto& buffer : buffers) {
|
||||
for (auto& handler : buf_handlers_) {
|
||||
if ((ret = (*handler.handler)(handler.arg, buffer)) != RTP_OK) {
|
||||
LOG_ERROR("Malfored packet");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return __sendtov(addr, buffers, flags, bytes_sent);
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::socket::__recv(uint8_t *buf, size_t buf_len, int flags, int *bytes_read)
|
||||
|
@ -520,17 +537,6 @@ rtp_error_t uvg_rtp::socket::__recvfrom(uint8_t *buf, size_t buf_len, int flags,
|
|||
return RTP_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
#ifdef __RTP_CRYPTO__
|
||||
if (srtp_) {
|
||||
auto status = srtp_->decrypt(buf, (size_t)ret);
|
||||
|
||||
if (status != RTP_OK) {
|
||||
LOG_ERROR("Failed to encrypt RTP packet!");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
set_bytes(bytes_read, ret);
|
||||
return RTP_OK;
|
||||
#else
|
||||
|
|
239
src/srtp.cc
239
src/srtp.cc
|
@ -55,6 +55,45 @@ rtp_error_t uvg_rtp::srtp::create_iv(uint8_t *out, uint32_t ssrc, uint64_t index
|
|||
return RTP_OK;
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::srtp::encrypt(uint32_t ssrc, uint16_t seq, uint8_t *buffer, size_t len)
|
||||
{
|
||||
if (use_null_cipher_)
|
||||
return RTP_OK;
|
||||
|
||||
uint8_t iv[16] = { 0 };
|
||||
uint64_t index = (((uint64_t)srtp_ctx_.roc) << 16) + seq;
|
||||
|
||||
/* Sequence number has wrapped around, update Roll-over Counter */
|
||||
if (seq == 0xffff)
|
||||
srtp_ctx_.roc++;
|
||||
|
||||
if (create_iv(iv, ssrc, index, srtp_ctx_.key_ctx.local.salt_key) != RTP_OK) {
|
||||
LOG_ERROR("Failed to create IV, unable to encrypt the RTP packet!");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
uvg_rtp::crypto::aes::ctr ctr(srtp_ctx_.key_ctx.local.enc_key, sizeof(srtp_ctx_.key_ctx.local.enc_key), iv);
|
||||
ctr.encrypt(buffer, buffer, len);
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
bool uvg_rtp::srtp::use_null_cipher()
|
||||
{
|
||||
return use_null_cipher_;
|
||||
}
|
||||
|
||||
bool uvg_rtp::srtp::authenticate_rtp()
|
||||
{
|
||||
return authenticate_rtp_;
|
||||
}
|
||||
|
||||
uvg_rtp::srtp_ctx_t& uvg_rtp::srtp::get_ctx()
|
||||
{
|
||||
return srtp_ctx_;
|
||||
}
|
||||
|
||||
>>>>>>> security-fixes
|
||||
rtp_error_t uvg_rtp::srtp::__init(int type, int flags)
|
||||
{
|
||||
srtp_ctx_.roc = 0;
|
||||
|
@ -66,8 +105,8 @@ rtp_error_t uvg_rtp::srtp::__init(int type, int flags)
|
|||
srtp_ctx_.mki_present = false;
|
||||
srtp_ctx_.mki = nullptr;
|
||||
|
||||
srtp_ctx_.master_key = key_ctx_.master.local_key;
|
||||
srtp_ctx_.master_salt = key_ctx_.master.local_salt;
|
||||
srtp_ctx_.master_key = srtp_ctx_.key_ctx.master.local_key;
|
||||
srtp_ctx_.master_salt = srtp_ctx_.key_ctx.master.local_salt;
|
||||
srtp_ctx_.mk_cnt = 0;
|
||||
|
||||
srtp_ctx_.n_e = AES_KEY_LENGTH;
|
||||
|
@ -82,46 +121,46 @@ rtp_error_t uvg_rtp::srtp::__init(int type, int flags)
|
|||
/* Local aka encryption keys */
|
||||
(void)derive_key(
|
||||
SRTP_ENCRYPTION,
|
||||
key_ctx_.master.local_key,
|
||||
key_ctx_.master.local_salt,
|
||||
key_ctx_.local.enc_key,
|
||||
srtp_ctx_.key_ctx.master.local_key,
|
||||
srtp_ctx_.key_ctx.master.local_salt,
|
||||
srtp_ctx_.key_ctx.local.enc_key,
|
||||
AES_KEY_LENGTH
|
||||
);
|
||||
(void)derive_key(
|
||||
SRTP_AUTHENTICATION,
|
||||
key_ctx_.master.local_key,
|
||||
key_ctx_.master.local_salt,
|
||||
key_ctx_.local.auth_key,
|
||||
srtp_ctx_.key_ctx.master.local_key,
|
||||
srtp_ctx_.key_ctx.master.local_salt,
|
||||
srtp_ctx_.key_ctx.local.auth_key,
|
||||
AES_KEY_LENGTH
|
||||
);
|
||||
(void)derive_key(
|
||||
SRTP_SALTING,
|
||||
key_ctx_.master.local_key,
|
||||
key_ctx_.master.local_salt,
|
||||
key_ctx_.local.salt_key,
|
||||
srtp_ctx_.key_ctx.master.local_key,
|
||||
srtp_ctx_.key_ctx.master.local_salt,
|
||||
srtp_ctx_.key_ctx.local.salt_key,
|
||||
SALT_LENGTH
|
||||
);
|
||||
|
||||
/* Remote aka decryption keys */
|
||||
(void)derive_key(
|
||||
SRTP_ENCRYPTION,
|
||||
key_ctx_.master.remote_key,
|
||||
key_ctx_.master.remote_salt,
|
||||
key_ctx_.remote.enc_key,
|
||||
srtp_ctx_.key_ctx.master.remote_key,
|
||||
srtp_ctx_.key_ctx.master.remote_salt,
|
||||
srtp_ctx_.key_ctx.remote.enc_key,
|
||||
AES_KEY_LENGTH
|
||||
);
|
||||
(void)derive_key(
|
||||
SRTP_AUTHENTICATION,
|
||||
key_ctx_.master.remote_key,
|
||||
key_ctx_.master.remote_salt,
|
||||
key_ctx_.remote.auth_key,
|
||||
srtp_ctx_.key_ctx.master.remote_key,
|
||||
srtp_ctx_.key_ctx.master.remote_salt,
|
||||
srtp_ctx_.key_ctx.remote.auth_key,
|
||||
AES_KEY_LENGTH
|
||||
);
|
||||
(void)derive_key(
|
||||
SRTP_SALTING,
|
||||
key_ctx_.master.remote_key,
|
||||
key_ctx_.master.remote_salt,
|
||||
key_ctx_.remote.salt_key,
|
||||
srtp_ctx_.key_ctx.master.remote_key,
|
||||
srtp_ctx_.key_ctx.master.remote_salt,
|
||||
srtp_ctx_.key_ctx.remote.salt_key,
|
||||
SALT_LENGTH
|
||||
);
|
||||
|
||||
|
@ -142,10 +181,10 @@ rtp_error_t uvg_rtp::srtp::init_zrtp(int type, int flags, uvg_rtp::rtp *rtp, uvg
|
|||
|
||||
/* ZRTP key derivation function expects the keys lengths to be given in bits */
|
||||
rtp_error_t ret = zrtp->get_srtp_keys(
|
||||
key_ctx_.master.local_key, AES_KEY_LENGTH * 8,
|
||||
key_ctx_.master.remote_key, AES_KEY_LENGTH * 8,
|
||||
key_ctx_.master.local_salt, SALT_LENGTH * 8,
|
||||
key_ctx_.master.remote_salt, SALT_LENGTH * 8
|
||||
srtp_ctx_.key_ctx.master.local_key, AES_KEY_LENGTH * 8,
|
||||
srtp_ctx_.key_ctx.master.remote_key, AES_KEY_LENGTH * 8,
|
||||
srtp_ctx_.key_ctx.master.local_salt, SALT_LENGTH * 8,
|
||||
srtp_ctx_.key_ctx.master.remote_salt, SALT_LENGTH * 8
|
||||
);
|
||||
|
||||
if (ret != RTP_OK) {
|
||||
|
@ -161,128 +200,102 @@ rtp_error_t uvg_rtp::srtp::init_user(int type, int flags, uint8_t *key, uint8_t
|
|||
if (!key || !salt)
|
||||
return RTP_INVALID_VALUE;
|
||||
|
||||
memcpy(key_ctx_.master.local_key, key, AES_KEY_LENGTH);
|
||||
memcpy(key_ctx_.master.remote_key, key, AES_KEY_LENGTH);
|
||||
memcpy(key_ctx_.master.local_salt, salt, SALT_LENGTH);
|
||||
memcpy(key_ctx_.master.remote_salt, salt, SALT_LENGTH);
|
||||
memcpy(srtp_ctx_.key_ctx.master.local_key, key, AES_KEY_LENGTH);
|
||||
memcpy(srtp_ctx_.key_ctx.master.remote_key, key, AES_KEY_LENGTH);
|
||||
memcpy(srtp_ctx_.key_ctx.master.local_salt, salt, SALT_LENGTH);
|
||||
memcpy(srtp_ctx_.key_ctx.master.remote_salt, salt, SALT_LENGTH);
|
||||
|
||||
return __init(type, flags);
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::srtp::__encrypt(uint32_t ssrc, uint16_t seq, uint8_t *buffer, size_t len)
|
||||
rtp_error_t uvg_rtp::srtp::recv_packet_handler(void *arg, int flags, frame::rtp_frame **out)
|
||||
{
|
||||
if (use_null_cipher_)
|
||||
return RTP_OK;
|
||||
(void)flags;
|
||||
|
||||
uint8_t iv[16] = { 0 };
|
||||
uint64_t index = (((uint64_t)srtp_ctx_.roc) << 16) + seq;
|
||||
uvg_rtp::srtp *srtp = (uvg_rtp::srtp *)arg;
|
||||
uvg_rtp::srtp_ctx_t ctx = srtp->get_ctx();
|
||||
uvg_rtp::frame::rtp_frame *frame = *out;
|
||||
|
||||
if (srtp->use_null_cipher())
|
||||
return RTP_PKT_NOT_HANDLED;
|
||||
|
||||
uint8_t iv[16] = { 0 };
|
||||
uint16_t seq = frame->header.seq;
|
||||
uint32_t ssrc = frame->header.ssrc;
|
||||
uint64_t index = (((uint64_t)ctx.roc) << 16) + seq;
|
||||
uint64_t digest = 0;
|
||||
|
||||
/* Sequence number has wrapped around, update Roll-over Counter */
|
||||
if (seq == 0xffff)
|
||||
srtp_ctx_.roc++;
|
||||
ctx.roc++;
|
||||
|
||||
if (create_iv(iv, ssrc, index, key_ctx_.local.salt_key) != RTP_OK) {
|
||||
if (srtp->create_iv(iv, ssrc, index, ctx.key_ctx.remote.salt_key) != RTP_OK) {
|
||||
LOG_ERROR("Failed to create IV, unable to encrypt the RTP packet!");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
uvg_rtp::crypto::aes::ctr ctr(key_ctx_.local.enc_key, sizeof(key_ctx_.local.enc_key), iv);
|
||||
ctr.encrypt(buffer, buffer, len);
|
||||
uvg_rtp::crypto::aes::ctr ctr(ctx.key_ctx.remote.enc_key, sizeof(ctx.key_ctx.remote.enc_key), iv);
|
||||
|
||||
/* exit early if RTP packet authentication is disabled... */
|
||||
if (!srtp->authenticate_rtp()) {
|
||||
ctr.decrypt(frame->payload, frame->payload, frame->payload_len);
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
/* ... otherwise calculate authentication tag for the packet
|
||||
* and compare it against the one we received */
|
||||
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(ctx.key_ctx.remote.auth_key, AES_KEY_LENGTH);
|
||||
|
||||
hmac_sha1.update((uint8_t *)frame, frame->payload_len - AUTH_TAG_LENGTH);
|
||||
hmac_sha1.update((uint8_t *)&ctx.roc, sizeof(ctx.roc));
|
||||
hmac_sha1.final((uint8_t *)&digest);
|
||||
|
||||
if (memcmp(&digest, &frame[frame->payload_len - AUTH_TAG_LENGTH], AUTH_TAG_LENGTH)) {
|
||||
LOG_ERROR("Authentication tag mismatch!");
|
||||
return RTP_AUTH_TAG_MISMATCH;
|
||||
}
|
||||
|
||||
size_t size_ = frame->payload_len - sizeof(uvg_rtp::frame::rtp_header) - 8;
|
||||
uint8_t *new_buffer = new uint8_t[size_];
|
||||
|
||||
ctr.decrypt(new_buffer, frame->payload, size_);
|
||||
memset(frame->payload, 0, frame->payload_len);
|
||||
memcpy(frame->payload, new_buffer, size_);
|
||||
delete[] new_buffer;
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::srtp::encrypt(uvg_rtp::frame::rtp_frame *frame)
|
||||
rtp_error_t uvg_rtp::srtp::send_packet_handler(void *arg, uvg_rtp::buf_vec& buffers)
|
||||
{
|
||||
/* TODO: authentication for complete RTP frame requires co-operation
|
||||
* with the allocator of that frame -> no good solution for that right now */
|
||||
auto srtp = (uvg_rtp::srtp *)arg;
|
||||
|
||||
return __encrypt(
|
||||
ntohl(frame->header.ssrc),
|
||||
ntohs(frame->header.seq),
|
||||
frame->payload,
|
||||
frame->payload_len
|
||||
);
|
||||
}
|
||||
if (srtp->use_null_cipher())
|
||||
return RTP_OK;
|
||||
|
||||
rtp_error_t uvg_rtp::srtp::encrypt(std::vector<std::pair<size_t, uint8_t *>>& buffers)
|
||||
{
|
||||
auto frame = (uvg_rtp::frame::rtp_frame *)buffers.at(0).second;
|
||||
auto rtp = buffers.at(buffers.size() - 1);
|
||||
uint64_t *digest = new uint64_t;
|
||||
auto frame = (uvg_rtp::frame::rtp_frame *)buffers.at(0).second;
|
||||
auto rtp = buffers.at(buffers.size() - 1);
|
||||
auto ctx = srtp->get_ctx();
|
||||
|
||||
rtp_error_t ret = __encrypt(
|
||||
rtp_error_t ret = srtp->encrypt(
|
||||
ntohl(frame->header.ssrc),
|
||||
ntohs(frame->header.seq),
|
||||
rtp.second,
|
||||
rtp.first
|
||||
);
|
||||
|
||||
if (!authenticate_rtp_)
|
||||
return ret;
|
||||
if (!srtp->authenticate_rtp())
|
||||
return RTP_OK;
|
||||
|
||||
/* create authentication tag for the packet and push it to the vector buffer */
|
||||
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(key_ctx_.local.auth_key, AES_KEY_LENGTH);
|
||||
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(ctx.key_ctx.local.auth_key, AES_KEY_LENGTH);
|
||||
|
||||
for (auto& buffer : buffers)
|
||||
hmac_sha1.update((uint8_t *)buffer.second, buffer.first);
|
||||
for (size_t i = 0; i < buffers.size() - 1; ++i)
|
||||
hmac_sha1.update((uint8_t *)buffers[i].second, buffers[i].first);
|
||||
|
||||
hmac_sha1.update((uint8_t *)&srtp_ctx_.roc, sizeof(srtp_ctx_.roc));
|
||||
hmac_sha1.final((uint8_t *)digest);
|
||||
hmac_sha1.update((uint8_t *)&ctx.roc, sizeof(ctx.roc));
|
||||
hmac_sha1.final((uint8_t *)buffers[buffers.size() - 1].second);
|
||||
|
||||
buffers.push_back(std::make_pair(sizeof(uint64_t), (uint8_t *)digest));
|
||||
return ret;
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::srtp::decrypt(uint8_t *buffer, size_t len)
|
||||
{
|
||||
if (use_null_cipher_)
|
||||
return RTP_OK;
|
||||
|
||||
uint8_t iv[16] = { 0 };
|
||||
auto hdr = (uvg_rtp::frame::rtp_header *)buffer;
|
||||
uint16_t seq = ntohs(hdr->seq);
|
||||
uint32_t ssrc = ntohl(hdr->ssrc);
|
||||
uint64_t index = (((uint64_t)srtp_ctx_.roc) << 16) + seq;
|
||||
uint64_t digest = 0;
|
||||
|
||||
/* Sequence number has wrapped around, update Roll-over Counter */
|
||||
if (seq == 0xffff)
|
||||
srtp_ctx_.roc++;
|
||||
|
||||
if (create_iv(iv, ssrc, index, key_ctx_.remote.salt_key) != RTP_OK) {
|
||||
LOG_ERROR("Failed to create IV, unable to encrypt the RTP packet!");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
uint8_t *payload = buffer + sizeof(uvg_rtp::frame::rtp_header);
|
||||
uvg_rtp::crypto::aes::ctr ctr(key_ctx_.remote.enc_key, sizeof(key_ctx_.remote.enc_key), iv);
|
||||
|
||||
/* exit early if RTP packet authentication is disabled... */
|
||||
if (!authenticate_rtp_) {
|
||||
ctr.decrypt(payload, payload, len - sizeof(uvg_rtp::frame::rtp_header));
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
/* ... otherwise calculate authentication tag for the packet
|
||||
* and compare it against the one we received */
|
||||
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(key_ctx_.remote.auth_key, AES_KEY_LENGTH);
|
||||
|
||||
hmac_sha1.update((uint8_t *)buffer, len - AUTH_TAG_LENGTH);
|
||||
hmac_sha1.update((uint8_t *)&srtp_ctx_.roc, sizeof(srtp_ctx_.roc));
|
||||
hmac_sha1.final((uint8_t *)&digest);
|
||||
|
||||
if (memcmp(&digest, &buffer[len - AUTH_TAG_LENGTH], AUTH_TAG_LENGTH)) {
|
||||
LOG_ERROR("Authentication tag mismatch!");
|
||||
return RTP_AUTH_TAG_MISMATCH;
|
||||
}
|
||||
|
||||
size_t size_ = len - sizeof(uvg_rtp::frame::rtp_header) - 8;
|
||||
uint8_t *new_buffer = new uint8_t[size_];
|
||||
|
||||
ctr.decrypt(new_buffer, payload, size_);
|
||||
memset(payload, 0, len);
|
||||
memcpy(payload, new_buffer, size_);
|
||||
return RTP_OK;
|
||||
}
|
||||
#endif
|
||||
|
|
47
src/zrtp.cc
47
src/zrtp.cc
|
@ -814,4 +814,51 @@ rtp_error_t uvg_rtp::zrtp::get_srtp_keys(
|
|||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
rtp_error_t uvg_rtp::zrtp::packet_handler(ssize_t size, void *packet, int flags, frame::rtp_frame **out)
|
||||
{
|
||||
(void)size, (void)flags, (void)out;
|
||||
|
||||
auto msg = (uvg_rtp::zrtp_msg::zrtp_msg *)packet;
|
||||
|
||||
/* not a ZRTP packet */
|
||||
if (msg->header.version || msg->header.magic != ZRTP_HEADER_MAGIC || msg->magic != ZRTP_MSG_MAGIC)
|
||||
return RTP_PKT_NOT_HANDLED;
|
||||
|
||||
switch (msg->msgblock) {
|
||||
/* None of these messages should be received by this stream
|
||||
* during this stage so return RTP_GENERIC_ERROR to indicate that the packet
|
||||
* is invalid and that it should not be dispatched to other packet handlers */
|
||||
case uvg_rtp::zrtp_msg::ZRTP_MSG_HELLO:
|
||||
case ZRTP_MSG_HELLO_ACK:
|
||||
case ZRTP_MSG_COMMIT:
|
||||
case ZRTP_MSG_DH_PART1:
|
||||
case ZRTP_MSG_DH_PART2:
|
||||
case ZRTP_MSG_CONFIRM1:
|
||||
case ZRTP_MSG_CONFIRM2:
|
||||
case ZRTP_MSG_CONF2_ACK:
|
||||
return RTP_GENERIC_ERROR;
|
||||
|
||||
case ZRTP_MSG_ERROR:
|
||||
/* TODO: */
|
||||
return RTP_OK;
|
||||
|
||||
case ZRTP_MSG_ERROR_ACK:
|
||||
/* TODO: */
|
||||
return RTP_OK;
|
||||
|
||||
case ZRTP_MSG_SAS_RELAY:
|
||||
return RTP_OK;
|
||||
|
||||
case ZRTP_MSG_RELAY_ACK:
|
||||
return RTP_OK;
|
||||
|
||||
case ZRTP_MSG_PING_ACK:
|
||||
return RTP_OK;
|
||||
|
||||
/* TODO: goclear & co-opeartion with srtp */
|
||||
}
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue