uvgrtp-base/docs/examples/srtp_user.cc

181 lines
6.2 KiB
C++
Raw Normal View History

2020-04-27 11:07:24 +00:00
#include <uvgrtp/lib.hh>
#include <climits>
// This example includes both sending and receiving SRTP streams.
// Normally these are done on separate machines
2020-04-27 11:07:24 +00:00
constexpr char SENDER_ADDRESS[] = "127.0.0.1";
constexpr uint16_t LOCAL_PORT = 8888;
constexpr char RECEIVER_ADDRESS[] = "127.0.0.1";
constexpr uint16_t REMOTE_PORT = 8890;
enum Key_length{SRTP_128 = 128, SRTP_196 = 196, SRTP_256 = 256};
constexpr Key_length KEY_SIZE = SRTP_256;
constexpr int KEY_SIZE_BYTES = KEY_SIZE/8;
constexpr int SALT_SIZE = 112;
constexpr int SALT_SIZE_BYTES = SALT_SIZE/8;
constexpr auto EXAMPLE_DURATION = std::chrono::milliseconds(10000);
constexpr int FRAME_RATE = 30; // fps
constexpr int SEND_TEST_PACKETS = (EXAMPLE_DURATION.count() - 1000)/1000*FRAME_RATE;
constexpr int PACKET_INTERVAL_MS = 1000/FRAME_RATE;
constexpr int RECEIVER_WAIT_TIME_MS = 100;
void process_frame(uvgrtp::frame::rtp_frame *frame)
{
std::string payload = std::string((char*)frame->payload, frame->payload_len);
std::cout << "Received SRTP frame. Payload: " << payload << std::endl;
/* When we receive a frame, the ownership of the frame belongs to us and
* when we're done with it, we need to deallocate the frame */
(void)uvgrtp::frame::dealloc_frame(frame);
}
void receive_func(uint8_t key[KEY_SIZE_BYTES], uint8_t salt[SALT_SIZE_BYTES])
2020-04-27 11:07:24 +00:00
{
/* See sending.cc for more details */
uvgrtp::context ctx;
uvgrtp::session *receiver_session = ctx.create_session(SENDER_ADDRESS);
2020-04-27 11:07:24 +00:00
/* Enable SRTP and let user manage keys */
2020-04-27 11:07:24 +00:00
unsigned flags = RCE_SRTP | RCE_SRTP_KMNGMNT_USER;
/* With user-managed keys, you have the option to use 192- and 256-bit keys.
*
* If 192- or 256-bit key size is specified in the flags, add_srtp_ctx() expects
* the key paramter to be 24 or 32 bytes long, respectively. */
flags |= RCE_SRTP_KEYSIZE_256;
2020-04-27 11:07:24 +00:00
/* See sending.cc for more details about create_stream() */
uvgrtp::media_stream *recv = receiver_session->create_stream(REMOTE_PORT, LOCAL_PORT,
RTP_FORMAT_GENERIC, flags);
// Receive frames by pulling for EXAMPLE_DURATION milliseconds
if (recv)
{
/* Before anything else can be done,
* add_srtp_ctx() must be called with the SRTP key and salt.
*
* All calls to "recv" that try to modify and or/use the newly
* created media stream before calling add_srtp_ctx() will fail */
recv->add_srtp_ctx(key, salt);
std::cout << "Start receiving frames for " << EXAMPLE_DURATION.count() << " ms" << std::endl;
auto start = std::chrono::steady_clock::now();
uvgrtp::frame::rtp_frame *frame = nullptr;
while (std::chrono::steady_clock::now() - start < EXAMPLE_DURATION)
{
/* You can specify a timeout for the operation and if the a frame is not received
* within that time limit, pull_frame() returns a nullptr
*
* The parameter tells how long time a frame is waited in milliseconds */
frame = recv->pull_frame(RECEIVER_WAIT_TIME_MS);
if (frame)
{
process_frame(frame);
}
}
receiver_session->destroy_stream(recv);
}
2020-05-15 04:46:50 +00:00
if (receiver_session)
{
ctx.destroy_session(receiver_session);
}
2020-04-27 11:07:24 +00:00
}
int main(void)
{
uvgrtp::context ctx;
if (!ctx.crypto_enabled())
{
std::cerr << "Cannot run SRTP example if crypto is not included in uvgRTP!"
<< std::endl;
return EXIT_FAILURE;
}
/* Key and salt for the SRTP session of sender and receiver
*
* NOTE: uvgRTP supports 128, 196 and 256 bit keys and 112 bit salts */
uint8_t key[KEY_SIZE_BYTES] = { 0 };
uint8_t salt[SALT_SIZE_BYTES] = { 0 };
/* initialize SRTP key and salt */
for (int i = 0; i < KEY_SIZE_BYTES; ++i)
2020-04-27 11:07:24 +00:00
key[i] = i;
for (int i = 0; i < SALT_SIZE_BYTES; ++i)
salt[i] = i * 2;
std::cout << "Starting uvgRTP SRTP user provided encryption key example. Using key:"
<< key << " and salt: " << salt << std::endl;
2020-04-27 11:07:24 +00:00
/* Create separate thread for the receiver */
std::thread receiver(receive_func, key, salt);
receiver.detach();
2020-04-27 11:07:24 +00:00
/* See sending.cc for more details */
uvgrtp::session *sender_session = ctx.create_session(RECEIVER_ADDRESS);
2020-04-27 11:07:24 +00:00
/* Enable SRTP and let user manage keys */
unsigned flags = RCE_SRTP | RCE_SRTP_KMNGMNT_USER | RCE_SRTP_KEYSIZE_256;
2020-04-27 11:07:24 +00:00
/* See sending.cc for more details about create_stream() */
uvgrtp::media_stream *send = sender_session->create_stream(LOCAL_PORT, REMOTE_PORT,
RTP_FORMAT_GENERIC, flags);
if (send)
{
/* Before anything else can be done,
* add_srtp_ctx() must be called with the SRTP key and salt.
*
* All calls to "send" that try to modify and or/use the newly
* created media stream before calling add_srtp_ctx() will fail
* if SRTP is enabled */
send->add_srtp_ctx(key, salt);
/* All media is now encrypted/decrypted automatically */
char *message = (char *)"Hello, world!";
size_t msg_len = strlen(message);
auto start = std::chrono::steady_clock::now();
for (unsigned int i = 0; i < SEND_TEST_PACKETS; ++i)
{
std::cout << "Sending frame " << i + 1 << '/' << SEND_TEST_PACKETS << std::endl;
if (send->push_frame((uint8_t *)message, msg_len, RTP_NO_FLAGS) != RTP_OK)
{
std::cerr << "Failed to send frame" << std::endl;
}
// wait until it is time to send the next frame. Included only for
// demostration purposes since you can use uvgRTP to send packets as fast as desired
auto time_since_start = std::chrono::steady_clock::now() - start;
auto next_frame_time = (i + 1)*std::chrono::milliseconds(PACKET_INTERVAL_MS);
if (next_frame_time > time_since_start)
{
std::this_thread::sleep_for(next_frame_time - time_since_start);
}
}
sender_session->destroy_stream(send);
}
2020-04-27 11:07:24 +00:00
if (sender_session)
ctx.destroy_session(sender_session);
return EXIT_SUCCESS;
2020-04-27 11:07:24 +00:00
}