multiplex: Rewrite ZRTP initialization to use new packet handler
This commit is contained in:
parent
81499a5c6d
commit
ac4f883d3f
|
@ -388,6 +388,8 @@ namespace uvgrtp {
|
|||
|
||||
rtp_error_t start_components();
|
||||
|
||||
rtp_error_t install_packet_handlers();
|
||||
|
||||
uint32_t get_default_bandwidth_kbps(rtp_format_t fmt);
|
||||
|
||||
bool check_pull_preconditions();
|
||||
|
|
|
@ -302,58 +302,68 @@ rtp_error_t uvgrtp::media_stream::free_resources(rtp_error_t ret)
|
|||
return ret;
|
||||
}
|
||||
|
||||
rtp_error_t uvgrtp::media_stream::install_packet_handlers()
|
||||
{
|
||||
reception_flow_->new_install_handler(
|
||||
1, remote_ssrc_,
|
||||
std::bind(&uvgrtp::rtp::new_packet_handler, rtp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5),
|
||||
nullptr);
|
||||
if (rce_flags_ & RCE_RTCP) {
|
||||
reception_flow_->new_install_handler(
|
||||
6, remote_ssrc_,
|
||||
std::bind(&uvgrtp::rtcp::new_recv_packet_handler_common, rtcp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5), rtcp_.get());
|
||||
}
|
||||
if (rce_flags_ & RCE_RTCP_MUX) {
|
||||
rtcp_->set_socket(socket_);
|
||||
reception_flow_->new_install_handler(
|
||||
2, remote_ssrc_,
|
||||
std::bind(&uvgrtp::rtcp::new_recv_packet_handler, rtcp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5), nullptr);
|
||||
}
|
||||
if (rce_flags_ & RCE_SRTP) {
|
||||
socket_->install_handler(srtp_.get(), srtp_->send_packet_handler);
|
||||
reception_flow_->new_install_handler(
|
||||
4, remote_ssrc_,
|
||||
std::bind(&uvgrtp::srtp::new_recv_packet_handler, srtp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5), srtp_.get());
|
||||
}
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
rtp_error_t uvgrtp::media_stream::init()
|
||||
{
|
||||
if (init_connection() != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to initialize the underlying socket");
|
||||
return free_resources(RTP_GENERIC_ERROR);
|
||||
}
|
||||
|
||||
|
||||
reception_flow_ = sfp_->get_reception_flow_ptr(socket_);
|
||||
|
||||
rtp_ = std::shared_ptr<uvgrtp::rtp>(new uvgrtp::rtp(fmt_, ssrc_, ipv6_));
|
||||
rtcp_ = std::shared_ptr<uvgrtp::rtcp>(new uvgrtp::rtcp(rtp_, ssrc_, remote_ssrc_, cname_, sfp_, rce_flags_));
|
||||
srtp_ = std::shared_ptr<uvgrtp::srtp>(new uvgrtp::srtp(rce_flags_));
|
||||
srtcp_ = std::shared_ptr<uvgrtp::srtcp>(new uvgrtp::srtcp());
|
||||
|
||||
socket_->install_handler(rtcp_.get(), rtcp_->send_packet_handler_vec);
|
||||
|
||||
reception_flow_->new_install_handler(
|
||||
1, remote_ssrc_,
|
||||
std::bind(&uvgrtp::rtp::new_packet_handler, rtp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5),
|
||||
nullptr);
|
||||
|
||||
if (rce_flags_ & RCE_RTCP) {
|
||||
/* If we are using ZRTP, we only install the ZRTP handler first. Rest of the handlers are installed after ZRTP is
|
||||
finished. If ZRTP is not enabled, we can install all the required handlers now */
|
||||
if ((rce_flags_ & RCE_SRTP_KMNGMNT_ZRTP) && zrtp_) {
|
||||
reception_flow_->new_install_handler(
|
||||
6, remote_ssrc_,
|
||||
std::bind(&uvgrtp::rtcp::new_recv_packet_handler_common, rtcp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5), rtcp_.get());
|
||||
3, remote_ssrc_,
|
||||
std::bind(&uvgrtp::zrtp::packet_handler, zrtp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5),
|
||||
nullptr);
|
||||
}
|
||||
if (rce_flags_ & RCE_RTCP_MUX) {
|
||||
rtcp_->set_socket(socket_);
|
||||
reception_flow_->new_install_handler(
|
||||
2, remote_ssrc_,
|
||||
std::bind(&uvgrtp::rtcp::new_recv_packet_handler, rtcp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5), nullptr);
|
||||
else {
|
||||
install_packet_handlers();
|
||||
}
|
||||
if (rce_flags_ & RCE_SRTP) {
|
||||
srtp_ = std::shared_ptr<uvgrtp::srtp>(new uvgrtp::srtp(rce_flags_));
|
||||
srtcp_ = std::shared_ptr<uvgrtp::srtcp>(new uvgrtp::srtcp());
|
||||
|
||||
socket_->install_handler(srtp_.get(), srtp_->send_packet_handler);
|
||||
|
||||
reception_flow_->new_install_handler(
|
||||
4, remote_ssrc_,
|
||||
std::bind(&uvgrtp::srtp::new_recv_packet_handler, srtp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5), srtp_.get());
|
||||
if ((rce_flags_ & RCE_SRTP_KMNGMNT_ZRTP) && zrtp_) {
|
||||
reception_flow_->new_install_handler(
|
||||
3, remote_ssrc_,
|
||||
std::bind(&uvgrtp::zrtp::new_packet_handler, zrtp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5),
|
||||
nullptr);
|
||||
}
|
||||
/* If we are using SRTP user keys, reception is started after SRTP is initalised in add_srtp_ctx() */
|
||||
if (rce_flags_ & RCE_SRTP_KMNGMNT_USER) {
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
return start_components();
|
||||
}
|
||||
|
||||
|
@ -377,6 +387,8 @@ rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)
|
|||
return free_resources(RTP_TIMEOUT);
|
||||
}
|
||||
}
|
||||
UVG_LOG_DEBUG("Starting multistream negotiation ----------");
|
||||
|
||||
}
|
||||
|
||||
ret = RTP_OK;
|
||||
|
@ -385,16 +397,19 @@ rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)
|
|||
return free_resources(ret);
|
||||
}
|
||||
|
||||
srtp_ = std::shared_ptr<uvgrtp::srtp>(new uvgrtp::srtp(rce_flags_));
|
||||
if ((ret = init_srtp_with_zrtp(rce_flags_, SRTP, srtp_, zrtp)) != RTP_OK)
|
||||
return free_resources(ret);
|
||||
|
||||
srtcp_ = std::shared_ptr<uvgrtp::srtcp>(new uvgrtp::srtcp());
|
||||
if ((ret = init_srtp_with_zrtp(rce_flags_, SRTCP, srtcp_, zrtp)) != RTP_OK)
|
||||
return free_resources(ret);
|
||||
|
||||
zrtp->dh_has_finished(); // only after the DH stream has gotten its keys, do we let non-DH stream perform ZRTP
|
||||
UVG_LOG_ERROR("ZRTP finished --------------");
|
||||
install_packet_handlers();
|
||||
|
||||
// Sleep is there to make sure that our last ZRTP messages get to their destination before any of our sent media
|
||||
// packets do. This can happen if the media packets are routed via a faster route.
|
||||
//std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
|
@ -410,65 +425,23 @@ rtp_error_t uvgrtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
|
|||
|
||||
unsigned int srtp_rce_flags = RCE_SRTP | RCE_SRTP_KMNGMNT_USER;
|
||||
rtp_error_t ret = RTP_OK;
|
||||
/*
|
||||
if (init_connection() != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to initialize the underlying socket");
|
||||
return free_resources(RTP_GENERIC_ERROR);
|
||||
}
|
||||
reception_flow_ = sfp_->get_reception_flow_ptr(socket_);*/
|
||||
|
||||
if ((rce_flags_ & srtp_rce_flags) != srtp_rce_flags)
|
||||
return free_resources(RTP_NOT_SUPPORTED);
|
||||
|
||||
//rtp_ = std::shared_ptr<uvgrtp::rtp> (new uvgrtp::rtp(fmt_, ssrc_, ipv6_));
|
||||
|
||||
//srtp_ = std::shared_ptr<uvgrtp::srtp> (new uvgrtp::srtp(rce_flags_));
|
||||
|
||||
// why are they local and remote key/salt the same?
|
||||
if ((ret = srtp_->init(SRTP, rce_flags_, key, key, salt, salt)) != RTP_OK) {
|
||||
UVG_LOG_WARN("Failed to initialize SRTP for media stream!");
|
||||
return free_resources(ret);
|
||||
}
|
||||
|
||||
// srtcp_ = std::shared_ptr<uvgrtp::srtcp> (new uvgrtp::srtcp());
|
||||
|
||||
if ((ret = srtcp_->init(SRTCP, rce_flags_, key, key, salt, salt)) != RTP_OK) {
|
||||
UVG_LOG_WARN("Failed to initialize SRTCP for media stream!");
|
||||
return free_resources(ret);
|
||||
}
|
||||
|
||||
//rtcp_ = std::shared_ptr<uvgrtp::rtcp> (new uvgrtp::rtcp(rtp_, ssrc_, remote_ssrc_, cname_, sfp_, srtcp_, rce_flags_));
|
||||
|
||||
//socket_->install_handler(rtcp_.get(), rtcp_->send_packet_handler_vec);
|
||||
//socket_->install_handler(srtp_.get(), srtp_->send_packet_handler);
|
||||
/*
|
||||
reception_flow_->new_install_handler(
|
||||
1, remote_ssrc_,
|
||||
std::bind(&uvgrtp::rtp::new_packet_handler, rtp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5),
|
||||
nullptr);
|
||||
|
||||
if (rce_flags_ & RCE_RTCP) {
|
||||
|
||||
reception_flow_->new_install_handler(
|
||||
6, remote_ssrc_,
|
||||
std::bind(&uvgrtp::rtcp::new_recv_packet_handler_common, rtcp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5), rtcp_.get());
|
||||
}
|
||||
if (rce_flags_ & RCE_RTCP_MUX) {
|
||||
rtcp_->set_socket(socket_);
|
||||
reception_flow_->new_install_handler(
|
||||
2, remote_ssrc_,
|
||||
std::bind(&uvgrtp::rtcp::new_recv_packet_handler, rtcp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5), nullptr);
|
||||
}
|
||||
|
||||
reception_flow_->new_install_handler(
|
||||
4, remote_ssrc_,
|
||||
std::bind(&uvgrtp::srtp::new_recv_packet_handler, srtp_, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5), srtp_.get());
|
||||
*/
|
||||
return RTP_OK;//start_components();
|
||||
return start_components();
|
||||
}
|
||||
|
||||
rtp_error_t uvgrtp::media_stream::start_components()
|
||||
|
|
|
@ -581,9 +581,9 @@ void uvgrtp::reception_flow::process_packet(int rce_flags)
|
|||
/* -------------------- ZRTP check --------------------------------- */
|
||||
// Magic Cookie 0x5a525450
|
||||
if (ntohl(*(uint32_t*)&ptr[4]) == 0x5a525450) {
|
||||
// TODO: Add functionality
|
||||
//UVG_LOG_INFO("ZRTP packet");
|
||||
retval = handlers->zrtp.handler(nullptr, rce_flags, &ptr[0], size, &frame);
|
||||
if (handlers->zrtp.handler != nullptr) {
|
||||
retval = handlers->zrtp.handler(nullptr, rce_flags, &ptr[0], size, &frame);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -592,27 +592,38 @@ void uvgrtp::reception_flow::process_packet(int rce_flags)
|
|||
retval = RTP_PKT_MODIFIED;
|
||||
|
||||
/* Create RTP header */
|
||||
retval = handlers->rtp.handler(nullptr, rce_flags, &ptr[0], size, &frame);
|
||||
if (handlers->rtp.handler != nullptr) {
|
||||
retval = handlers->rtp.handler(nullptr, rce_flags, &ptr[0], size, &frame);
|
||||
}
|
||||
else {
|
||||
UVG_LOG_INFO("RTP handler is null");
|
||||
}
|
||||
|
||||
/* If SRTP is enabled -> send through SRTP handler */
|
||||
if (rce_flags & RCE_SRTP && retval == RTP_PKT_MODIFIED) {
|
||||
retval = handlers->srtp.handler(handlers->srtp.args, rce_flags, &ptr[0], size, &frame);
|
||||
if (handlers->srtp.handler != nullptr) {
|
||||
retval = handlers->srtp.handler(handlers->srtp.args, rce_flags, &ptr[0], size, &frame);
|
||||
}
|
||||
}
|
||||
/* Update RTCP session statistics */
|
||||
if (rce_flags & RCE_RTCP) {
|
||||
retval = handlers->rtcp_common.handler(handlers->rtcp_common.args, rce_flags, &ptr[0], size, &frame);
|
||||
if (handlers->rtcp_common.handler != nullptr) {
|
||||
retval = handlers->rtcp_common.handler(handlers->rtcp_common.args, rce_flags, &ptr[0], size, &frame);
|
||||
}
|
||||
}
|
||||
|
||||
/* If packet is ok, hand over to media handler */
|
||||
if (retval == RTP_PKT_MODIFIED || retval == RTP_PKT_NOT_HANDLED) {
|
||||
retval = handlers->media.handler(handlers->media.args, rce_flags, &ptr[0], size, &frame);
|
||||
if (handlers->media.handler && frame) {
|
||||
retval = handlers->media.handler(handlers->media.args, rce_flags, &ptr[0], size, &frame);
|
||||
}
|
||||
/* Last, if one or more packets are ready, return them to the user */
|
||||
if (retval == RTP_PKT_READY) {
|
||||
return_frame(frame);
|
||||
break;
|
||||
}
|
||||
else if (retval == RTP_MULTIPLE_PKTS_READY && handlers->getter != nullptr) {
|
||||
UVG_LOG_INFO("TODO:is this correct???");
|
||||
//UVG_LOG_INFO("TODO:is this correct???");
|
||||
while (handlers->getter(&frame) == RTP_PKT_READY) {
|
||||
return_frame(frame);
|
||||
}
|
||||
|
|
680
src/zrtp.cc
680
src/zrtp.cc
|
@ -36,8 +36,16 @@ uvgrtp::zrtp::zrtp():
|
|||
remote_ip6_addr_(),
|
||||
initialized_(false),
|
||||
receiver_(),
|
||||
dh_finished_(false),
|
||||
state_(0)
|
||||
hello_(nullptr),
|
||||
hello_ack_(nullptr),
|
||||
commit_(nullptr),
|
||||
dh1_(nullptr),
|
||||
dh2_(nullptr),
|
||||
conf1_(nullptr),
|
||||
conf2_(nullptr),
|
||||
confack_(nullptr),
|
||||
type_(-1),
|
||||
len_(0)
|
||||
{
|
||||
cctx_.sha256 = new uvgrtp::crypto::sha256;
|
||||
cctx_.dh = new uvgrtp::crypto::dh;
|
||||
|
@ -373,20 +381,71 @@ bool uvgrtp::zrtp::are_we_initiator(uint8_t *our_hvi, uint8_t *their_hvi)
|
|||
|
||||
rtp_error_t uvgrtp::zrtp::begin_session()
|
||||
{
|
||||
auto hello = uvgrtp::zrtp_msg::hello(session_);
|
||||
auto hello_ack = uvgrtp::zrtp_msg::hello_ack();
|
||||
auto hello = uvgrtp::zrtp_msg::hello(session_);
|
||||
auto hello_ack = uvgrtp::zrtp_msg::hello_ack();
|
||||
bool hello_recv = false;
|
||||
|
||||
uvgrtp::clock::hrc::hrc_t start = uvgrtp::clock::hrc::now();
|
||||
int interval = 50;
|
||||
int i = 1;
|
||||
|
||||
|
||||
while (true) {
|
||||
|
||||
/* We received something interesting, either Hello message from remote in which case
|
||||
* we need to send HelloACK message back and keep sending our Hello until HelloACK is received,
|
||||
* or HelloACK message which means we can stop sending our */
|
||||
|
||||
/* We received Hello message from remote, parse it and send */
|
||||
if (hello_ != nullptr) {
|
||||
UVG_LOG_DEBUG("Got ZRTP Hello. Sending Hello ACK");
|
||||
hello_ack.send_msg(local_socket_, remote_addr_, remote_ip6_addr_);
|
||||
|
||||
if (!hello_recv) {
|
||||
hello_recv = true;
|
||||
|
||||
/* Copy interesting information from receiver's
|
||||
* message buffer to remote capabilities struct for later use */
|
||||
hello.parse_msg(hello_, session_, len_);
|
||||
UVG_LOG_INFO("ZRTP Hello parsed");
|
||||
if (session_.capabilities.version != ZRTP_VERSION) {
|
||||
|
||||
/* Section 4.1.1:
|
||||
*
|
||||
* "If an endpoint receives a Hello message with an unsupported
|
||||
* version number that is lower than the endpoint's current Hello
|
||||
* message, the endpoint MUST send an Error message (Section 5.9)
|
||||
* indicating failure to support this ZRTP version."
|
||||
*/
|
||||
if (session_.capabilities.version < ZRTP_VERSION) {
|
||||
UVG_LOG_ERROR("Remote supports version %d, uvgRTP supports %d. Session cannot continue!",
|
||||
session_.capabilities.version, ZRTP_VERSION);
|
||||
|
||||
return RTP_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
UVG_LOG_WARN("ZRTP Protocol version %u not supported, keep sending Hello Messages",
|
||||
session_.capabilities.version);
|
||||
hello_recv = false;
|
||||
}
|
||||
}
|
||||
/* We received ACK for our Hello message.
|
||||
* Make sure we've received Hello message also before exiting */
|
||||
}
|
||||
if (hello_ack_ != nullptr) {
|
||||
|
||||
if (hello_recv)
|
||||
{
|
||||
UVG_LOG_DEBUG("Got Hello ACK! Ending Hello phase");
|
||||
return RTP_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
UVG_LOG_DEBUG("Got Hello ACK without Hello!");
|
||||
}
|
||||
}
|
||||
long int next_sendslot = i * interval;
|
||||
long int run_time = (long int)uvgrtp::clock::hrc::diff_now(start);
|
||||
long int diff_ms = next_sendslot - run_time;
|
||||
int type = 0;
|
||||
int poll_timeout = (int)diff_ms;
|
||||
|
||||
if (diff_ms < 0) {
|
||||
UVG_LOG_DEBUG("Sending ZRTP hello # %i", i);
|
||||
|
@ -394,73 +453,14 @@ rtp_error_t uvgrtp::zrtp::begin_session()
|
|||
UVG_LOG_ERROR("Failed to send Hello message");
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else if (receiver_.recv_msg(local_socket_, poll_timeout, 0, type) == RTP_OK) {
|
||||
/* We received something interesting, either Hello message from remote in which case
|
||||
* we need to send HelloACK message back and keep sending our Hello until HelloACK is received,
|
||||
* or HelloACK message which means we can stop sending our */
|
||||
|
||||
/* We received Hello message from remote, parse it and send */
|
||||
if (type == ZRTP_FT_HELLO) {
|
||||
UVG_LOG_DEBUG("Got ZRTP Hello. Sending Hello ACK");
|
||||
hello_ack.send_msg(local_socket_, remote_addr_, remote_ip6_addr_);
|
||||
|
||||
if (!hello_recv) {
|
||||
hello_recv = true;
|
||||
|
||||
/* Copy interesting information from receiver's
|
||||
* message buffer to remote capabilities struct for later use */
|
||||
hello.parse_msg(receiver_, session_);
|
||||
|
||||
if (session_.capabilities.version != ZRTP_VERSION) {
|
||||
|
||||
/* Section 4.1.1:
|
||||
*
|
||||
* "If an endpoint receives a Hello message with an unsupported
|
||||
* version number that is lower than the endpoint's current Hello
|
||||
* message, the endpoint MUST send an Error message (Section 5.9)
|
||||
* indicating failure to support this ZRTP version."
|
||||
*/
|
||||
if (session_.capabilities.version < ZRTP_VERSION) {
|
||||
UVG_LOG_ERROR("Remote supports version %d, uvgRTP supports %d. Session cannot continue!",
|
||||
session_.capabilities.version, ZRTP_VERSION);
|
||||
|
||||
return RTP_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
UVG_LOG_WARN("ZRTP Protocol version %u not supported, keep sending Hello Messages",
|
||||
session_.capabilities.version);
|
||||
hello_recv = false;
|
||||
}
|
||||
}
|
||||
/* We received ACK for our Hello message.
|
||||
* Make sure we've received Hello message also before exiting */
|
||||
}
|
||||
else if (type == ZRTP_FT_HELLO_ACK) {
|
||||
|
||||
if (hello_recv)
|
||||
{
|
||||
UVG_LOG_DEBUG("Got Hello ACK!");
|
||||
return RTP_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
UVG_LOG_DEBUG("Got Hello ACK without Hello!");
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* at this point we do not care about other messages */
|
||||
UVG_LOG_DEBUG("Got an unknown ZRTP message!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UVG_LOG_DEBUG("Did not get any ZRTP messages on try # %i", i);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(diff_ms));
|
||||
if (interval < 200) {
|
||||
interval *= 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(diff_ms));
|
||||
}
|
||||
|
||||
if (i > 20) {
|
||||
break;
|
||||
}
|
||||
|
@ -473,23 +473,21 @@ rtp_error_t uvgrtp::zrtp::begin_session()
|
|||
rtp_error_t uvgrtp::zrtp::init_session(int key_agreement)
|
||||
{
|
||||
/* Create ZRTP session from capabilities struct we've constructed */
|
||||
session_.hash_algo = S256;
|
||||
session_.cipher_algo = AES1;
|
||||
session_.auth_tag_type = HS32;
|
||||
session_.hash_algo = S256;
|
||||
session_.cipher_algo = AES1;
|
||||
session_.auth_tag_type = HS32;
|
||||
session_.key_agreement_type = key_agreement;
|
||||
session_.sas_type = B32;
|
||||
session_.sas_type = B32;
|
||||
|
||||
int type = 0;
|
||||
auto commit = uvgrtp::zrtp_msg::commit(session_);
|
||||
auto commit = uvgrtp::zrtp_msg::commit(session_);
|
||||
|
||||
/* First check if remote has already sent the message.
|
||||
* If so, they are the initiator and we're the responder */
|
||||
while (receiver_.recv_msg(local_socket_, 0, MSG_DONTWAIT, type) != RTP_INTERRUPTED) {
|
||||
if (type == ZRTP_FT_COMMIT) {
|
||||
commit.parse_msg(receiver_, session_);
|
||||
session_.role = RESPONDER;
|
||||
return RTP_OK;
|
||||
}
|
||||
if (commit_ != nullptr) {
|
||||
commit.parse_msg(commit_, session_, len_);
|
||||
session_.role = RESPONDER;
|
||||
UVG_LOG_DEBUG("------1------------RESPONDER");
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
/* If we proceed to sending Commit message, we can assume we're the initiator.
|
||||
|
@ -500,43 +498,45 @@ rtp_error_t uvgrtp::zrtp::init_session(int key_agreement)
|
|||
int interval = 150;
|
||||
int i = 1;
|
||||
|
||||
while (true) {
|
||||
while (true) {
|
||||
if (commit_) {
|
||||
|
||||
/* As per RFC 6189, if both parties have sent Commit message and the mode is DH,
|
||||
* hvi shall determine who is the initiator (the party with larger hvi is initiator) */
|
||||
commit.parse_msg(commit_, session_, len_);
|
||||
|
||||
/* Our hvi is smaller than remote's meaning we are the responder.
|
||||
*
|
||||
* Commit message must be ACKed with DHPart1 messages so we need exit,
|
||||
* construct that message and sent it to remote */
|
||||
|
||||
if (!are_we_initiator(session_.hash_ctx.o_hvi, session_.hash_ctx.r_hvi)) {
|
||||
session_.role = RESPONDER;
|
||||
UVG_LOG_DEBUG("------------------RESPONDER");
|
||||
return RTP_OK;
|
||||
}
|
||||
}
|
||||
if (dh1_ || conf1_) {
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
long int next_sendslot = i * interval;
|
||||
long int run_time = (long int)uvgrtp::clock::hrc::diff_now(start);
|
||||
long int diff_ms = next_sendslot - run_time;
|
||||
int poll_timeout = (int)diff_ms;
|
||||
|
||||
if (diff_ms < 0) {
|
||||
if (commit.send_msg(local_socket_, remote_addr_, remote_ip6_addr_) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to send Commit message!");
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else if (receiver_.recv_msg(local_socket_, poll_timeout, 0, type) == RTP_OK) {
|
||||
|
||||
/* As per RFC 6189, if both parties have sent Commit message and the mode is DH,
|
||||
* hvi shall determine who is the initiator (the party with larger hvi is initiator) */
|
||||
if (type == ZRTP_FT_COMMIT) {
|
||||
commit.parse_msg(receiver_, session_);
|
||||
|
||||
/* Our hvi is smaller than remote's meaning we are the responder.
|
||||
*
|
||||
* Commit message must be ACKed with DHPart1 messages so we need exit,
|
||||
* construct that message and sent it to remote */
|
||||
if (!are_we_initiator(session_.hash_ctx.o_hvi, session_.hash_ctx.r_hvi)) {
|
||||
session_.role = RESPONDER;
|
||||
return RTP_OK;
|
||||
}
|
||||
} else if (type == ZRTP_FT_DH_PART1 || type == ZRTP_FT_CONFIRM1) {
|
||||
return RTP_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(diff_ms));
|
||||
UVG_LOG_DEBUG("Commit sent");
|
||||
if (interval < 1200) {
|
||||
interval *= 2;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
|
||||
}
|
||||
if (i > 10) {
|
||||
break;
|
||||
|
@ -549,61 +549,57 @@ rtp_error_t uvgrtp::zrtp::init_session(int key_agreement)
|
|||
|
||||
rtp_error_t uvgrtp::zrtp::dh_part1()
|
||||
{
|
||||
auto dhpart = uvgrtp::zrtp_msg::dh_key_exchange(session_, 1);
|
||||
int type = 0;
|
||||
auto dhpart = uvgrtp::zrtp_msg::dh_key_exchange(session_, 1);
|
||||
uvgrtp::clock::hrc::hrc_t start = uvgrtp::clock::hrc::now();
|
||||
int interval = 150;
|
||||
int i = 1;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (dh2_ != nullptr) {
|
||||
if (dhpart.parse_msg(dh2_, session_, len_) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to parse DHPart2 Message!");
|
||||
continue;
|
||||
}
|
||||
UVG_LOG_DEBUG("DHPart2 received and parse successfully!");
|
||||
|
||||
/* parse_msg() above extracted the public key of remote and saved it to session_.
|
||||
* Now we must generate shared secrets (DHResult, total_hash, and s0) */
|
||||
generate_shared_secrets_dh();
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
long int next_sendslot = i * interval;
|
||||
long int run_time = (long int)uvgrtp::clock::hrc::diff_now(start);
|
||||
long int diff_ms = next_sendslot - run_time;
|
||||
int poll_timeout = (int)diff_ms;
|
||||
|
||||
if (diff_ms < 0) {
|
||||
if (dhpart.send_msg(local_socket_, remote_addr_, remote_ip6_addr_) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to send DHPart1 Message!");
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (receiver_.recv_msg(local_socket_, poll_timeout, 0, type) == RTP_OK) {
|
||||
if (type == ZRTP_FT_DH_PART2) {
|
||||
if (dhpart.parse_msg(receiver_, session_) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to parse DHPart2 Message!");
|
||||
continue;
|
||||
}
|
||||
UVG_LOG_DEBUG("DHPart2 received and parse successfully!");
|
||||
|
||||
/* parse_msg() above extracted the public key of remote and saved it to session_.
|
||||
* Now we must generate shared secrets (DHResult, total_hash, and s0) */
|
||||
generate_shared_secrets_dh();
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(diff_ms));
|
||||
UVG_LOG_DEBUG("DHPart1 sent");
|
||||
if (interval < 1200) {
|
||||
interval *= 2;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
|
||||
}
|
||||
if (i > 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return RTP_TIMEOUT;
|
||||
}
|
||||
|
||||
rtp_error_t uvgrtp::zrtp::dh_part2()
|
||||
{
|
||||
int type = 0;
|
||||
rtp_error_t ret = RTP_OK;
|
||||
auto dhpart = uvgrtp::zrtp_msg::dh_key_exchange(session_, 2);
|
||||
auto dhpart = uvgrtp::zrtp_msg::dh_key_exchange(session_, 2);
|
||||
|
||||
if ((ret = dhpart.parse_msg(receiver_, session_)) != RTP_OK) {
|
||||
if ((ret = dhpart.parse_msg(dh1_, session_, len_)) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to parse DHPart1 Message!");
|
||||
return ret;
|
||||
}
|
||||
|
@ -617,30 +613,28 @@ rtp_error_t uvgrtp::zrtp::dh_part2()
|
|||
int i = 1;
|
||||
|
||||
while (true) {
|
||||
if (conf1_ != nullptr) {
|
||||
UVG_LOG_DEBUG("Confirm1 Message received");
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
long int next_sendslot = i * interval;
|
||||
long int run_time = (long int)uvgrtp::clock::hrc::diff_now(start);
|
||||
long int diff_ms = next_sendslot - run_time;
|
||||
int poll_timeout = (int)diff_ms;
|
||||
|
||||
if (diff_ms < 0) {
|
||||
if ((ret = dhpart.send_msg(local_socket_, remote_addr_, remote_ip6_addr_)) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to send DHPart2 Message!");
|
||||
return ret;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (receiver_.recv_msg(local_socket_, poll_timeout, 0, type) == RTP_OK) {
|
||||
if (type == ZRTP_FT_CONFIRM1) {
|
||||
UVG_LOG_DEBUG("Confirm1 Message received");
|
||||
return RTP_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(diff_ms));
|
||||
UVG_LOG_DEBUG("DHPart2 sent");
|
||||
if (interval < 1200) {
|
||||
interval *= 2;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
if (i > 10) {
|
||||
break;
|
||||
|
@ -651,68 +645,65 @@ rtp_error_t uvgrtp::zrtp::dh_part2()
|
|||
|
||||
rtp_error_t uvgrtp::zrtp::responder_finalize_session()
|
||||
{
|
||||
auto confirm = uvgrtp::zrtp_msg::confirm(session_, 1);
|
||||
auto confack = uvgrtp::zrtp_msg::confack(session_);
|
||||
int type = 0;
|
||||
auto confirm = uvgrtp::zrtp_msg::confirm(session_, 1);
|
||||
auto confack = uvgrtp::zrtp_msg::confack(session_);
|
||||
uvgrtp::clock::hrc::hrc_t start = uvgrtp::clock::hrc::now();
|
||||
int interval = 150;
|
||||
int i = 1;
|
||||
|
||||
while (true) {
|
||||
if (conf2_ != nullptr) {
|
||||
if (confirm.parse_msg(conf2_, session_) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to parse Confirm2 Message!");
|
||||
continue;
|
||||
}
|
||||
|
||||
rtp_error_t ret = RTP_OK;
|
||||
if ((ret = validate_session()) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Mismatch on one of the received MACs/Hashes, session cannot continue");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: send in a loop? */
|
||||
confack.send_msg(local_socket_, remote_addr_, remote_ip6_addr_);
|
||||
UVG_LOG_DEBUG("ConfACK sent");
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
long int next_sendslot = i * interval;
|
||||
long int run_time = (long int)uvgrtp::clock::hrc::diff_now(start);
|
||||
long int diff_ms = next_sendslot - run_time;
|
||||
int poll_timeout = (int)diff_ms;
|
||||
|
||||
if (diff_ms < 0) {
|
||||
if (confirm.send_msg(local_socket_, remote_addr_, remote_ip6_addr_) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to send Confirm1 Message!");
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (receiver_.recv_msg(local_socket_, poll_timeout, 0, type) == RTP_OK) {
|
||||
if (type == ZRTP_FT_CONFIRM2) {
|
||||
if (confirm.parse_msg(receiver_, session_) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to parse Confirm2 Message!");
|
||||
continue;
|
||||
}
|
||||
|
||||
rtp_error_t ret = RTP_OK;
|
||||
if ((ret = validate_session()) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Mismatch on one of the received MACs/Hashes, session cannot continue");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: send in a loop? */
|
||||
confack.send_msg(local_socket_, remote_addr_, remote_ip6_addr_);
|
||||
return RTP_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(diff_ms));
|
||||
UVG_LOG_DEBUG("Confirm1 sent");
|
||||
if (interval < 1200) {
|
||||
interval *= 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
if (i > 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return RTP_TIMEOUT;
|
||||
}
|
||||
|
||||
rtp_error_t uvgrtp::zrtp::initiator_finalize_session()
|
||||
{
|
||||
rtp_error_t ret = RTP_OK;
|
||||
auto confirm = uvgrtp::zrtp_msg::confirm(session_, 2);
|
||||
int type = 0;
|
||||
auto confirm = uvgrtp::zrtp_msg::confirm(session_, 2);
|
||||
uvgrtp::clock::hrc::hrc_t start = uvgrtp::clock::hrc::now();
|
||||
int interval = 150;
|
||||
int i = 1;
|
||||
|
||||
if ((ret = confirm.parse_msg(receiver_, session_)) != RTP_OK) {
|
||||
if ((ret = confirm.parse_msg(conf1_, session_)) != RTP_OK) {
|
||||
UVG_LOG_ERROR("Failed to parse Confirm1 Message!");
|
||||
return ret;
|
||||
}
|
||||
|
@ -723,10 +714,14 @@ rtp_error_t uvgrtp::zrtp::initiator_finalize_session()
|
|||
}
|
||||
|
||||
while (true) {
|
||||
if (confack_ != nullptr) {
|
||||
UVG_LOG_DEBUG("Conf2ACK received successfully!");
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
long int next_sendslot = i * interval;
|
||||
long int run_time = (long int)uvgrtp::clock::hrc::diff_now(start);
|
||||
long int diff_ms = next_sendslot - run_time;
|
||||
int poll_timeout = (int)diff_ms;
|
||||
|
||||
if (diff_ms < 0) {
|
||||
if ((ret = confirm.send_msg(local_socket_, remote_addr_, remote_ip6_addr_)) != RTP_OK) {
|
||||
|
@ -734,20 +729,13 @@ rtp_error_t uvgrtp::zrtp::initiator_finalize_session()
|
|||
return ret;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (receiver_.recv_msg(local_socket_, poll_timeout, 0, type) == RTP_OK) {
|
||||
if (type == ZRTP_FT_CONF2_ACK) {
|
||||
UVG_LOG_DEBUG("Conf2ACK received successfully!");
|
||||
return RTP_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(diff_ms));
|
||||
if (interval < 1200) {
|
||||
interval *= 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
if (i > 10) {
|
||||
break;
|
||||
}
|
||||
|
@ -799,6 +787,15 @@ rtp_error_t uvgrtp::zrtp::init_dhm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket
|
|||
UVG_LOG_DEBUG("Starting ZRTP Diffie-Hellman negotiation with %s", uvgrtp::socket::sockaddr_to_string(addr).c_str());
|
||||
}
|
||||
|
||||
hello_ = nullptr;
|
||||
hello_ack_ = nullptr;
|
||||
commit_ = nullptr;
|
||||
dh1_ = nullptr;
|
||||
dh2_ = nullptr;
|
||||
conf1_ = nullptr;
|
||||
conf2_ = nullptr;
|
||||
confack_ = nullptr;
|
||||
|
||||
/* TODO: set all fields initially to zero */
|
||||
memset(session_.hash_ctx.o_hvi, 0, sizeof(session_.hash_ctx.o_hvi));
|
||||
|
||||
|
@ -836,7 +833,6 @@ rtp_error_t uvgrtp::zrtp::init_dhm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket
|
|||
* message. This should be calculated now because the next step is choosing
|
||||
* the the roles for participants. */
|
||||
auto dh_msg = uvgrtp::zrtp_msg::dh_key_exchange(session_, 2);
|
||||
|
||||
cctx_.sha256->update((uint8_t *)session_.l_msg.dh.second, session_.l_msg.dh.first);
|
||||
cctx_.sha256->update((uint8_t *)session_.r_msg.hello.second, session_.r_msg.hello.first);
|
||||
cctx_.sha256->final((uint8_t *)session_.hash_ctx.o_hvi);
|
||||
|
@ -879,16 +875,16 @@ rtp_error_t uvgrtp::zrtp::init_dhm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket
|
|||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
UVG_LOG_INFO("ZRTP has been initialized using DHMode");
|
||||
/* ZRTP has been initialized using DHMode */
|
||||
initialized_ = true;
|
||||
|
||||
/* reset the timeout (no longer needed) */
|
||||
/*
|
||||
/* reset the timeout (no longer needed)
|
||||
struct timeval tv = { 0, 0 };
|
||||
|
||||
if (local_socket_->setsockopt(SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)) != RTP_OK)
|
||||
return RTP_GENERIC_ERROR;
|
||||
|
||||
*/
|
||||
/* Session has been initialized successfully and SRTP can start */
|
||||
return RTP_OK;
|
||||
}
|
||||
|
@ -904,6 +900,15 @@ rtp_error_t uvgrtp::zrtp::init_msm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket
|
|||
session_.ssrc = ssrc;
|
||||
session_.seq = 0;
|
||||
|
||||
hello_ = nullptr;
|
||||
hello_ack_ = nullptr;
|
||||
commit_ = nullptr;
|
||||
dh1_ = nullptr;
|
||||
dh2_ = nullptr;
|
||||
conf1_ = nullptr;
|
||||
conf2_ = nullptr;
|
||||
confack_ = nullptr;
|
||||
|
||||
UVG_LOG_DEBUG("Generating ZRTP keys in multistream mode");
|
||||
|
||||
if ((ret = begin_session()) != RTP_OK) {
|
||||
|
@ -968,7 +973,7 @@ rtp_error_t uvgrtp::zrtp::get_srtp_keys(
|
|||
return RTP_OK;
|
||||
}
|
||||
|
||||
rtp_error_t uvgrtp::zrtp::new_packet_handler(void* args, int rce_flags, uint8_t* read_ptr, size_t size, frame::rtp_frame** out)
|
||||
rtp_error_t uvgrtp::zrtp::packet_handler(void* args, int rce_flags, uint8_t* read_ptr, size_t size, frame::rtp_frame** out)
|
||||
{
|
||||
if (size < 0 || (uint32_t)size < sizeof(uvgrtp::zrtp_msg::zrtp_msg))
|
||||
{
|
||||
|
@ -985,60 +990,283 @@ rtp_error_t uvgrtp::zrtp::new_packet_handler(void* args, int rce_flags, uint8_t*
|
|||
if (msg->header.version || msg->preamble != ZRTP_PREAMBLE) {
|
||||
return RTP_PKT_NOT_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
rtp_error_t uvgrtp::zrtp::packet_handler(ssize_t size, void *packet, int rce_flags, frame::rtp_frame **out)
|
||||
{
|
||||
if (size < 0 || (uint32_t)size < sizeof(uvgrtp::zrtp_msg::zrtp_msg))
|
||||
{
|
||||
return RTP_PKT_NOT_HANDLED;
|
||||
}
|
||||
|
||||
(void)rce_flags;
|
||||
(void)out;
|
||||
|
||||
auto msg = (uvgrtp::zrtp_msg::zrtp_msg *)packet;
|
||||
|
||||
/* not a ZRTP packet */
|
||||
if (msg->header.version || msg->header.magic != ZRTP_MAGIC || msg->preamble != ZRTP_PREAMBLE)
|
||||
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 uvgrtp::zrtp_msg::ZRTP_MSG_HELLO:
|
||||
case ZRTP_MSG_HELLO:
|
||||
{
|
||||
// TODO: Check length based on algorithms
|
||||
if (msg->length < 22) // see rfc 6189 section 5.8
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Hello length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP Hello message received, verify CRC32!");
|
||||
zrtp_hello* hello = (zrtp_hello*)msg;
|
||||
|
||||
if (!uvgrtp::crypto::crc32::verify_crc32(read_ptr, size - 4, hello->crc)) {
|
||||
return RTP_NOT_SUPPORTED;
|
||||
}
|
||||
if (hello_ != nullptr) {
|
||||
//UVG_LOG_DEBUG("Already got Hello, discarding new one");
|
||||
return RTP_OK;
|
||||
}
|
||||
hello_ = hello;
|
||||
type_ = ZRTP_FT_HELLO;
|
||||
len_ = size;
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
|
||||
case ZRTP_MSG_HELLO_ACK:
|
||||
{
|
||||
if (msg->length != 3) // see rfc 6189 section 5.3
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Hello ACK length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP HelloACK message received, verify CRC32!");
|
||||
|
||||
zrtp_hello_ack* ha_msg = (zrtp_hello_ack*)msg;
|
||||
|
||||
if (!uvgrtp::crypto::crc32::verify_crc32(read_ptr, size - 4, ha_msg->crc))
|
||||
return RTP_NOT_SUPPORTED;
|
||||
if (hello_ack_ != nullptr) {
|
||||
//UVG_LOG_DEBUG("Already got HelloACK, discarding new one");
|
||||
return RTP_OK;
|
||||
}
|
||||
hello_ack_ = ha_msg;
|
||||
type_ = ZRTP_FT_HELLO_ACK;
|
||||
len_ = size;
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_COMMIT:
|
||||
{
|
||||
if (msg->length != 29 &&
|
||||
msg->length != 25 &&
|
||||
msg->length != 27) // see rfc 6189 section 5.4
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Commit length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP Commit message received, verify CRC32!");
|
||||
|
||||
zrtp_commit* commit = (zrtp_commit*)msg;
|
||||
|
||||
if (!uvgrtp::crypto::crc32::verify_crc32(read_ptr, size - 4, commit->crc))
|
||||
return RTP_NOT_SUPPORTED;
|
||||
|
||||
if (commit_ != nullptr) {
|
||||
UVG_LOG_DEBUG("Already got Commit, discarding new one");
|
||||
return RTP_OK;
|
||||
}
|
||||
commit_ = commit;
|
||||
type_ = ZRTP_FT_COMMIT;
|
||||
len_ = size;
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_DH_PART1:
|
||||
{
|
||||
// TODO: Check based on KA type
|
||||
if (msg->length < 21) // see rfc 6189 section 5.5
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP DH Part1 length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP DH Part1 message received, verify CRC32!");
|
||||
|
||||
zrtp_dh* dh = (zrtp_dh*)msg;
|
||||
|
||||
if (!uvgrtp::crypto::crc32::verify_crc32(read_ptr, size - 4, dh->crc))
|
||||
return RTP_NOT_SUPPORTED;
|
||||
|
||||
if (dh1_ != nullptr) {
|
||||
UVG_LOG_DEBUG("Already got DHPart1, discarding new one");
|
||||
return RTP_OK;
|
||||
}
|
||||
dh1_ = dh;
|
||||
type_ = ZRTP_FT_DH_PART1;
|
||||
len_ = size;
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_DH_PART2:
|
||||
{
|
||||
// TODO: Check based on KA type
|
||||
if (msg->length < 21) // see rfc 6189 section 5.6
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP DH Part2 length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP DH Part2 message received, verify CRC32!");
|
||||
|
||||
zrtp_dh* dh = (zrtp_dh*)msg;
|
||||
|
||||
if (!uvgrtp::crypto::crc32::verify_crc32(read_ptr, size - 4, dh->crc))
|
||||
return RTP_NOT_SUPPORTED;
|
||||
|
||||
if (dh2_ != nullptr) {
|
||||
UVG_LOG_DEBUG("Already got DHPart2, discarding new one");
|
||||
return RTP_OK;
|
||||
}
|
||||
dh2_ = dh;
|
||||
type_ = ZRTP_FT_DH_PART2;
|
||||
len_ = size;
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_CONFIRM1:
|
||||
{
|
||||
// TODO: Check based on signiture
|
||||
if (msg->length < 19) // see rfc 6189 section 5.6
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Confirm1 length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
rtp_error_t ret = RTP_OK;
|
||||
UVG_LOG_DEBUG("ZRTP Confirm1 message received, verify CRC32!");
|
||||
|
||||
zrtp_confirm* dh = (zrtp_confirm*)msg;
|
||||
|
||||
if (!uvgrtp::crypto::crc32::verify_crc32(read_ptr, size - 4, dh->crc))
|
||||
return RTP_NOT_SUPPORTED;
|
||||
|
||||
if (conf1_ != nullptr) {
|
||||
UVG_LOG_DEBUG("Already got Confirm1, discarding new one");
|
||||
return RTP_OK;
|
||||
}
|
||||
conf1_ = dh;
|
||||
type_ = ZRTP_FT_CONFIRM1;
|
||||
len_ = size;
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_CONFIRM2:
|
||||
{
|
||||
// TODO: Check based on signiture
|
||||
if (msg->length < 19) // see rfc 6189 section 5.6
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Confirm1 length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP Confirm2 message received, verify CRC32!");
|
||||
|
||||
zrtp_confirm* dh = (zrtp_confirm*)msg;
|
||||
|
||||
if (!uvgrtp::crypto::crc32::verify_crc32(read_ptr, size - 4, dh->crc))
|
||||
return RTP_NOT_SUPPORTED;
|
||||
|
||||
if (conf2_ != nullptr) {
|
||||
UVG_LOG_DEBUG("Already got Confirm2, discarding new one");
|
||||
return RTP_OK;
|
||||
}
|
||||
conf2_ = dh;
|
||||
type_ = ZRTP_FT_CONFIRM2;
|
||||
len_ = size;
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_CONF2_ACK:
|
||||
return RTP_GENERIC_ERROR;
|
||||
{
|
||||
if (msg->length != 3) // see rfc 6189 section 5.8
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Conf2 ACK length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP Conf2 ACK message received, verify CRC32!");
|
||||
|
||||
zrtp_confack* ca = (zrtp_confack*)msg;
|
||||
|
||||
if (!uvgrtp::crypto::crc32::verify_crc32(read_ptr, size - 4, ca->crc))
|
||||
return RTP_NOT_SUPPORTED;
|
||||
|
||||
if (confack_ != nullptr) {
|
||||
UVG_LOG_DEBUG("Already got Conf2ACK, discarding new one");
|
||||
return RTP_OK;
|
||||
}
|
||||
confack_ = ca;
|
||||
type_ = ZRTP_FT_CONF2_ACK;
|
||||
len_ = size;
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_ERROR:
|
||||
/* TODO: */
|
||||
{
|
||||
if (msg->length != 4) // see rfc 6189 section 5.9
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Error length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP Error message received");
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_ERROR_ACK:
|
||||
/* TODO: */
|
||||
{
|
||||
if (msg->length != 3) // see rfc 6189 section 5.10
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Error ACK length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP Error ACK message received");
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_SAS_RELAY:
|
||||
{
|
||||
// TODO: Check based on signiture
|
||||
if (msg->length < 19) // see rfc 6189 section 5.14
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP SAS Relay length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP SAS Relay message received");
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_RELAY_ACK:
|
||||
{
|
||||
if (msg->length != 3) // see rfc 6189 section 5.14
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Relay ACK length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP Relay ACK message received");
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
case ZRTP_MSG_PING_ACK:
|
||||
{
|
||||
if (msg->length != 9) // see rfc 6189 section 5.16
|
||||
{
|
||||
UVG_LOG_WARN("ZRTP Relay ACK length field is wrong");
|
||||
return RTP_INVALID_VALUE;
|
||||
}
|
||||
|
||||
UVG_LOG_DEBUG("ZRTP Ping ACK message received");
|
||||
return RTP_OK;
|
||||
}
|
||||
|
||||
/* TODO: goclear & co-opeartion with srtp */
|
||||
default: {
|
||||
return RTP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return RTP_OK;
|
||||
}
|
||||
}
|
29
src/zrtp.hh
29
src/zrtp.hh
|
@ -2,7 +2,12 @@
|
|||
|
||||
#include "zrtp/zrtp_receiver.hh"
|
||||
#include "zrtp/defines.hh"
|
||||
|
||||
#include "zrtp/commit.hh"
|
||||
#include "zrtp/confack.hh"
|
||||
#include "zrtp/confirm.hh"
|
||||
#include "zrtp/dh_kxchng.hh"
|
||||
#include "zrtp/hello.hh"
|
||||
#include "zrtp/hello_ack.hh"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
|
@ -64,7 +69,8 @@ namespace uvgrtp {
|
|||
uint8_t *their_msalt, uint32_t tsalt_len
|
||||
);
|
||||
|
||||
/* ZRTP packet handler is used after ZRTP state initialization has finished
|
||||
/* TODO REWRITE THIS
|
||||
ZRTP packet handler is used after ZRTP state initialization has finished
|
||||
* and media exchange has started. RTP reception flow gives the packet
|
||||
* to "zrtp_handler" which then checks whether the packet is a ZRTP packet
|
||||
* or not and processes it accordingly.
|
||||
|
@ -72,8 +78,7 @@ namespace uvgrtp {
|
|||
* 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 rce_flags, frame::rtp_frame **out);
|
||||
rtp_error_t new_packet_handler(void* args, int rce_flags, uint8_t* read_ptr, size_t size, frame::rtp_frame** out);
|
||||
rtp_error_t packet_handler(void* args, int rce_flags, uint8_t* read_ptr, size_t size, frame::rtp_frame** out);
|
||||
|
||||
inline bool has_dh_finished() const
|
||||
{
|
||||
|
@ -120,7 +125,6 @@ namespace uvgrtp {
|
|||
/* Derive new key using s0 as HMAC key */
|
||||
void derive_key(const char *label, uint32_t key_len, uint8_t *key);
|
||||
|
||||
rtp_error_t new_begin_session();
|
||||
/* Being the ZRTP session by sending a Hello message to remote,
|
||||
* and responding to remote's Hello message using HelloAck message
|
||||
*
|
||||
|
@ -193,9 +197,20 @@ namespace uvgrtp {
|
|||
|
||||
std::mutex zrtp_mtx_;
|
||||
|
||||
bool dh_finished_ = false;
|
||||
int state_;
|
||||
uvgrtp::zrtp_msg::zrtp_hello* hello_;
|
||||
uvgrtp::zrtp_msg::zrtp_hello_ack* hello_ack_;
|
||||
uvgrtp::zrtp_msg::zrtp_commit* commit_;
|
||||
uvgrtp::zrtp_msg::zrtp_dh* dh1_;
|
||||
uvgrtp::zrtp_msg::zrtp_dh* dh2_;
|
||||
uvgrtp::zrtp_msg::zrtp_confirm* conf1_;
|
||||
uvgrtp::zrtp_msg::zrtp_confirm* conf2_;
|
||||
uvgrtp::zrtp_msg::zrtp_confack* confack_;
|
||||
int type_;
|
||||
size_t len_;
|
||||
std::mutex state_mutex_;
|
||||
bool dh_finished_ = false;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue