Skip to content

Commit

Permalink
common: Add possibility only send or only receive
Browse files Browse the repository at this point in the history
The API forced uvgRTP to both bind to local port even if user does not
need or want this and it also expects the user to know the remote
remote address which is not always possible.

This commit adds API to session for specifying only one port when
creating media_stream. This commit also adds RCE_SEND_ONLY and
RCE_RECEIVE_ONLY flags which can be used to prevent binding and specify
the meaning of single address and port parameters.
  • Loading branch information
jrsnen committed Sep 6, 2022
1 parent fe28c42 commit d68fcb0
Show file tree
Hide file tree
Showing 9 changed files with 283 additions and 189 deletions.
2 changes: 1 addition & 1 deletion include/uvgrtp/context.hh
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace uvgrtp {
* \retval nullptr If "remote_addr" is empty
* \retval nullptr If memory allocation failed
*/
uvgrtp::session *create_session(std::string remote_addr);
uvgrtp::session *create_session(std::string address);

/**
* \brief Create a new RTP session
Expand Down
27 changes: 3 additions & 24 deletions include/uvgrtp/media_stream.hh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ namespace uvgrtp {
class media_stream {
public:
/// \cond DO_NOT_DOCUMENT
media_stream(std::string cname, std::string addr, uint16_t src_port, uint16_t dst_port, rtp_format_t fmt, int rce_flags);
media_stream(std::string cname, std::string remote_addr, std::string local_addr, uint16_t src_port, uint16_t dst_port,
rtp_format_t fmt, int rce_flags);
~media_stream();
Expand Down Expand Up @@ -240,29 +239,6 @@ namespace uvgrtp {
* \retval RTP_INVALID_VALUE If hook is nullptr */
rtp_error_t install_receive_hook(void *arg, void (*hook)(void *, uvgrtp::frame::rtp_frame *));

/// \cond DO_NOT_DOCUMENT
/*
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if "hook" is nullptr */
rtp_error_t install_deallocation_hook(void (*hook)(void *));

/* If needed, a notification hook can be installed to uvgRTP that can be used as
* an information side channel to the internal state of the library.
*
* When uvgRTP encouters a situation it doesn't know how to react to,
* it calls the notify hook with certain notify reason number (src/util.hh).
* Upon receiving a notification, application may ignore it or act on it somehow
*
* Currently only one notification type is supported and only receiver uses notifications
*
* "arg" is optional argument that is passed to hook when it is called. It may be nullptr
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if "hook" is nullptr */
rtp_error_t install_notify_hook(void *arg, void (*hook)(void *, int));
/// \endcond

/**
* \brief Configure the media stream, see ::RTP_CTX_CONFIGURATION_FLAGS for more details
*
Expand Down Expand Up @@ -320,6 +296,9 @@ namespace uvgrtp {

uint32_t get_default_bandwidth_kbps(rtp_format_t fmt);

bool check_pull_preconditions();
rtp_error_t check_push_preconditions();

uint32_t key_;

std::shared_ptr<uvgrtp::srtp> srtp_;
Expand Down
2 changes: 1 addition & 1 deletion include/uvgrtp/rtcp.hh
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ namespace uvgrtp {
* (or whether we're even sending anything)
*
* Return RTP_OK on success and RTP_ERROR on error */
rtp_error_t add_participant(std::string dst_addr, uint16_t dst_port, uint16_t src_port, uint32_t clock_rate);
rtp_error_t add_participant(std::string src_addr, std::string dst_addr, uint16_t dst_port, uint16_t src_port, uint32_t clock_rate);

/* Functions for updating various RTP sender statistics */
void sender_update_stats(const uvgrtp::frame::rtp_frame *frame);
Expand Down
60 changes: 44 additions & 16 deletions include/uvgrtp/session.hh
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ namespace uvgrtp {
public:
/// \cond DO_NOT_DOCUMENT
session(std::string cname, std::string addr);
session(std::string cname, std::string remote_addr,
std::string local_addr);
session(std::string cname, std::string remote_addr, std::string local_addr);
~session();
/// \endcond

Expand All @@ -31,33 +30,60 @@ namespace uvgrtp {
*
* \details
*
* If local_addr was provided when uvgrtp::session was created, uvgRTP binds
* itself to local_addr:src_port, otherwise to INADDR_ANY:src_port
* If both addresses were provided when uvgrtp::session was created, uvgRTP binds
* itself to local_addr:src_port and sends packets to remote_addr:dst_port.
*
* If only one address was provided, the RCE_SEND_ONLY flag in rce_flags can be used to
* avoid binding and src_port is thus ignored. RCE_RECEIVE_ONLY means dst_port is ignored.
* Without either, the one address is interpreted as remote_addr and binding happens to ANY.
*
* This object is used for both sending and receiving media, see documentation
* for uvgrtp::media_stream for more details.
*
* User can enable and disable functionality of uvgRTP by OR'ing RCE_* flags
* User can enable and disable functionality of uvgRTP by OR'ing (using |) RCE_* flags
* together and passing them using the rce_flags parameter
*
* \param src_port Local port that uvgRTP listens to for incoming RTP packets
* \param dst_port Remote port where uvgRTP sends RTP packets
* \param fmt Format of the media stream. see ::RTP_FORMAT for more details
* \param rce_flags RTP context enable flags, see ::RTP_CTX_ENABLE_FLAGS for more details
* \param src_port Local port that uvgRTP listens to for incoming RTP packets
* \param dst_port Remote port where uvgRTP sends RTP packets
* \param fmt Format of the media stream. see ::RTP_FORMAT for more details
* \param rce_flags RTP context enable flags, see ::RTP_CTX_ENABLE_FLAGS for more details
*
* \return RTP media stream object
*
* \retval uvgrtp::media_stream* On success
* \retval nullptr If src_port or dst_port is 0
* \retval nullptr If fmt is not a supported media format
* \retval nullptr If socket initialization failed
* \retval nullptr If ZRTP was enabled and it failed to finish handshaking
* \retval nullptr If RCE_SRTP is given but uvgRTP has not been compiled with Crypto++ enabled
* \retval nullptr If RCE_SRTP is given but RCE_SRTP_KMNGMNT_* flag is not given
* \retval nullptr If memory allocation failed
* \retval nullptr On failure, see print and
*/
uvgrtp::media_stream *create_stream(uint16_t src_port, uint16_t dst_port, rtp_format_t fmt, int rce_flags);

/**
* \brief Create a bidirectional media stream for an RTP session
*
* \details
*
* If both addresses were provided when uvgrtp::session was created, uvgRTP binds
* sends packets to remote_addr:port and does not bind.
*
* If only one address was provided, the RCE_SEND_ONLY flag in rce_flags can be used to
* avoid binding and port is used as remote_port. RCE_RECEIVE_ONLY means port is used for binding.
* Without either, the one address is interpreted as remote_addr and binding happens to ANY.
*
* This object is used for both sending and receiving media, see documentation
* for uvgrtp::media_stream for more details.
*
* User can enable and disable functionality of uvgRTP by OR'ing (using |) RCE_* flags
* together and passing them using the rce_flags parameter
*
* \param port Either local or remote port depending on rce_flags
* \param fmt Format of the media stream. see ::RTP_FORMAT for more details
* \param rce_flags RTP context enable flags, see ::RTP_CTX_ENABLE_FLAGS for more details
*
* \return RTP media stream object
*
* \retval uvgrtp::media_stream* On success
* \retval nullptr On failure, see print
*/
uvgrtp::media_stream *create_stream(uint16_t port, rtp_format_t fmt, int rce_flags);

/**
* \brief Destroy a media stream
*
Expand All @@ -81,6 +107,8 @@ namespace uvgrtp {
/* Each RTP multimedia session shall have one ZRTP session from which all session are derived */
std::shared_ptr<uvgrtp::zrtp> zrtp_;

std::string generic_address_;

/* Each RTP multimedia session is always IP-specific */
std::string remote_address_;

Expand Down
51 changes: 28 additions & 23 deletions include/uvgrtp/util.hh
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,19 @@ typedef enum RTP_FLAGS {
enum RTP_CTX_ENABLE_FLAGS {
RCE_NO_FLAGS = 0,

// Obsolete flags
RCE_SYSTEM_CALL_DISPATCHER = 0,
RCE_NO_H26X_INTRA_DELAY = 0,
RCE_NO_H26X_SCL = 0,
RCE_H26X_NO_DEPENDENCY_ENFORCEMENT = 0,
// Obsolete flags, they do nothing because the feature has been removed or they are enabled by default
RCE_OBSOLETE = 1, // for checking if user inputs obsolete flags
RCE_SYSTEM_CALL_DISPATCHER = 1, // removed feature
RCE_NO_H26X_INTRA_DELAY = 1, // removed feature
RCE_NO_H26X_SCL = 1, // this flag was moved to be an RTP flag
RCE_H26X_NO_DEPENDENCY_ENFORCEMENT = 1, // the feature is disabled by default

// These can be used to specify what the address does for one address create session
RCE_SEND_ONLY = 1 << 1, // address interpreted as remote, no binding to socket
RCE_RECEIVE_ONLY = 1 << 2, // address interpreted as local, sending not possible

/** Use SRTP for this connection */
RCE_SRTP = 1,
RCE_SRTP = 1 << 3,

/** Use ZRTP for key management
*
Expand All @@ -204,7 +209,7 @@ enum RTP_CTX_ENABLE_FLAGS {
*
* This flag must be coupled with RCE_SRTP and is mutually exclusive
* with RCE_SRTP_KMNGMNT_USER. */
RCE_SRTP_KMNGMNT_ZRTP = 1 << 1,
RCE_SRTP_KMNGMNT_ZRTP = 1 << 4,

/** Use user-defined way to manage keys
*
Expand All @@ -214,24 +219,24 @@ enum RTP_CTX_ENABLE_FLAGS {
*
* This flag must be coupled with RCE_SRTP and is mutually exclusive
* with RCE_SRTP_KMNGMNT_ZRTP */
RCE_SRTP_KMNGMNT_USER = 1 << 2,
RCE_SRTP_KMNGMNT_USER = 1 << 5,

/** By default, the RTP packet payload does not include the start code prefixes.
* Use this flag to prepend the 4-byte start code (0x00000001) to each received
* H26x frame, so there is no difference with sender input. Recommended in
* most cases. */
RCE_H26X_PREPEND_SC = 1 << 3,
RCE_H26X_PREPEND_SC = 1 << 6,

/** Use this flag to discard inter frames that don't have their previous dependencies
arrived. Does not work if the dependencies are not in monotonic order. */
RCE_H26X_DEPENDENCY_ENFORCEMENT = 1 << 4,
RCE_H26X_DEPENDENCY_ENFORCEMENT = 1 << 7,

/** Fragment frames into RTP packets of MTU size (1500 bytes).
*
* Some RTP profiles define fragmentation with marker bit indicating the end of frame.
* You can enable this functionality using this flag at both sender and receiver.
*/
RCE_FRAGMENT_GENERIC = 1 << 5,
RCE_FRAGMENT_GENERIC = 1 << 8,

/** If SRTP is enabled and RCE_INPLACE_ENCRYPTION flag is *not* given,
* uvgRTP will make a copy of the frame given to push_frame().
Expand All @@ -241,45 +246,45 @@ enum RTP_CTX_ENABLE_FLAGS {
* unnecessary copy operations.
*
* If RCE_INPLACE_ENCRYPTION is given to push_frame(), the input pointer must be writable! */
RCE_SRTP_INPLACE_ENCRYPTION = 1 << 6,
RCE_SRTP_INPLACE_ENCRYPTION = 1 << 9,

/** Disable System Call Clustering (SCC) */
RCE_NO_SYSTEM_CALL_CLUSTERING = 1 << 7,
RCE_NO_SYSTEM_CALL_CLUSTERING = 1 << 10,

/** Disable RTP payload encryption */
RCE_SRTP_NULL_CIPHER = 1 << 8,
RCE_SRTP_NULL_CIPHER = 1 << 11,

/** Enable RTP packet authentication
*
* This flag forces the security layer to add authentication tag
* to each outgoing RTP packet for all streams that have SRTP enabled.
*
* NOTE: this flag must be coupled with at least RCE_SRTP */
RCE_SRTP_AUTHENTICATE_RTP = 1 << 9,
RCE_SRTP_AUTHENTICATE_RTP = 1 << 12,

/** Enable packet replay protection */
RCE_SRTP_REPLAY_PROTECTION = 1 << 10,
RCE_SRTP_REPLAY_PROTECTION = 1 << 13,

/** Enable RTCP for the media stream.
* If SRTP is enabled, SRTCP is used instead */
RCE_RTCP = 1 << 11,
RCE_RTCP = 1 << 14,

/** If the Mediastream object is used as a unidirectional stream
* but holepunching has been enabled, this flag can be used to make
* uvgRTP periodically send a short UDP datagram to keep the hole
* in the firewall open */
RCE_HOLEPUNCH_KEEPALIVE = 1 << 12,
RCE_HOLEPUNCH_KEEPALIVE = 1 << 15,

/** Use 192-bit keys with SRTP */
RCE_SRTP_KEYSIZE_192 = 1 << 13,
RCE_SRTP_KEYSIZE_192 = 1 << 16,

/** Use 256-bit keys with SRTP */
RCE_SRTP_KEYSIZE_256 = 1 << 14,
RCE_SRTP_KEYSIZE_256 = 1 << 17,

RCE_ZRTP_MULTISTREAM_NO_DH = 1 << 16,
RCE_ZRTP_MULTISTREAM_NO_DH = 1 << 18,

RCE_LAST = 1 << 17,
};
RCE_LAST = 1 << 19
}; // maximum is 1 << 30 for int


/**
Expand Down
14 changes: 10 additions & 4 deletions src/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,24 @@ uvgrtp::context::~context()
#endif
}

uvgrtp::session *uvgrtp::context::create_session(std::string remote_addr)
uvgrtp::session *uvgrtp::context::create_session(std::string address)
{
if (remote_addr == "")
if (address == "")
{
UVG_LOG_ERROR("Please specify the address you want to communicate with!");
return nullptr;
}

return new uvgrtp::session(get_cname(), remote_addr);
return new uvgrtp::session(get_cname(), address);
}

uvgrtp::session *uvgrtp::context::create_session(std::string remote_addr, std::string local_addr)
{
if (remote_addr == "" || local_addr == "")
if (remote_addr == "" && local_addr == "")
{
UVG_LOG_ERROR("Please specify at least one address for create_session");
return nullptr;
}

return new uvgrtp::session(get_cname(), remote_addr, local_addr);
}
Expand Down
Loading

0 comments on commit d68fcb0

Please sign in to comment.