mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
RTC: Covert basic packet identify for DTLS/STUN/RTP/RTCP
This commit is contained in:
parent
49e768ad09
commit
d439e36344
2 changed files with 124 additions and 12 deletions
|
@ -97,6 +97,7 @@ void SrsRtcBlackhole::sendto(void* data, int len)
|
|||
return;
|
||||
}
|
||||
|
||||
// For blackhole, we ignore any error.
|
||||
srs_sendto(blackhole_stfd, data, len, (sockaddr*)blackhole_addr, sizeof(sockaddr_in), SRS_UTIME_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
|
@ -105,24 +106,32 @@ SrsRtcBlackhole* _srs_blackhole = new SrsRtcBlackhole();
|
|||
// @global dtls certficate for rtc module.
|
||||
SrsDtlsCertificate* _srs_rtc_dtls_certificate = new SrsDtlsCertificate();
|
||||
|
||||
static bool is_stun(const uint8_t* data, const int size)
|
||||
// TODO: Should support error response.
|
||||
// For STUN packet, 0x00 is binding request, 0x01 is binding success response.
|
||||
bool srs_is_stun(const uint8_t* data, size_t size)
|
||||
{
|
||||
return data != NULL && size > 0 && (data[0] == 0 || data[0] == 1);
|
||||
return size > 0 && (data[0] == 0 || data[0] == 1);
|
||||
}
|
||||
|
||||
static bool is_dtls(const uint8_t* data, size_t len)
|
||||
// change_cipher_spec(20), alert(21), handshake(22), application_data(23)
|
||||
// @see https://tools.ietf.org/html/rfc2246#section-6.2.1
|
||||
bool srs_is_dtls(const uint8_t* data, size_t len)
|
||||
{
|
||||
return (len >= 13 && (data[0] > 19 && data[0] < 64));
|
||||
return (len >= 13 && (data[0] > 19 && data[0] < 64));
|
||||
}
|
||||
|
||||
static bool is_rtp_or_rtcp(const uint8_t* data, size_t len)
|
||||
// For RTP or RTCP, the V=2 which is in the high 2bits, 0xC0 (1100 0000)
|
||||
bool srs_is_rtp_or_rtcp(const uint8_t* data, size_t len)
|
||||
{
|
||||
return (len >= 12 && (data[0] & 0xC0) == 0x80);
|
||||
return (len >= 12 && (data[0] & 0xC0) == 0x80);
|
||||
}
|
||||
|
||||
static bool is_rtcp(const uint8_t* data, size_t len)
|
||||
// For RTCP, PT is [128, 223] (or without marker [0, 95]).
|
||||
// Literally, RTCP starts from 64 not 0, so PT is [192, 223] (or without marker [64, 95]).
|
||||
// @note For RTP, the PT is [96, 127], or [224, 255] with marker.
|
||||
bool srs_is_rtcp(const uint8_t* data, size_t len)
|
||||
{
|
||||
return (len >= 12) && (data[0] & 0x80) && (data[1] >= 200 && data[1] <= 209);
|
||||
return (len >= 12) && (data[0] & 0x80) && (data[1] >= 192 && data[1] <= 223);
|
||||
}
|
||||
|
||||
static std::vector<std::string> get_candidate_ips()
|
||||
|
@ -301,7 +310,7 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt)
|
|||
}
|
||||
|
||||
// For STUN, the peer address may change.
|
||||
if (is_stun((uint8_t*)data, size)) {
|
||||
if (srs_is_stun((uint8_t*)data, size)) {
|
||||
SrsStunPacket ping;
|
||||
if ((err = ping.decode(data, size)) != srs_success) {
|
||||
return srs_error_wrap(err, "decode stun packet failed");
|
||||
|
@ -332,10 +341,10 @@ srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt)
|
|||
return srs_error_new(ERROR_RTC_STUN, "no session, peer_id=%s", peer_id.c_str());
|
||||
}
|
||||
|
||||
if (is_dtls((uint8_t*)data, size)) {
|
||||
if (srs_is_dtls((uint8_t*)data, size)) {
|
||||
return session->on_dtls(data, size);
|
||||
} else if (is_rtp_or_rtcp((uint8_t*)data, size)) {
|
||||
if (is_rtcp((uint8_t*)data, size)) {
|
||||
} else if (srs_is_rtp_or_rtcp((uint8_t*)data, size)) {
|
||||
if (srs_is_rtcp((uint8_t*)data, size)) {
|
||||
return session->on_rtcp(data, size);
|
||||
}
|
||||
return session->on_rtp(data, size);
|
||||
|
|
|
@ -29,6 +29,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <srs_app_rtc_source.hpp>
|
||||
#include <srs_app_rtc_conn.hpp>
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
VOID TEST(KernelRTCTest, SequenceCompare)
|
||||
{
|
||||
if (true) {
|
||||
|
@ -125,6 +128,106 @@ VOID TEST(KernelRTCTest, SequenceCompare)
|
|||
}
|
||||
}
|
||||
|
||||
extern bool srs_is_stun(const uint8_t* data, size_t size);
|
||||
extern bool srs_is_dtls(const uint8_t* data, size_t len);
|
||||
extern bool srs_is_rtp_or_rtcp(const uint8_t* data, size_t len);
|
||||
extern bool srs_is_rtcp(const uint8_t* data, size_t len);
|
||||
|
||||
#define mock_arr_push(arr, elem) arr.push_back(vector<uint8_t>(elem, elem + sizeof(elem)))
|
||||
|
||||
VOID TEST(KernelRTCTest, TestPacketType)
|
||||
{
|
||||
// DTLS packet.
|
||||
vector< vector<uint8_t> > dtlss;
|
||||
if (true) { uint8_t data[13] = {20}; mock_arr_push(dtlss, data); } // change_cipher_spec(20)
|
||||
if (true) { uint8_t data[13] = {21}; mock_arr_push(dtlss, data); } // alert(21)
|
||||
if (true) { uint8_t data[13] = {22}; mock_arr_push(dtlss, data); } // handshake(22)
|
||||
if (true) { uint8_t data[13] = {23}; mock_arr_push(dtlss, data); } // application_data(23)
|
||||
for (int i = 0; i < (int)dtlss.size(); i++) {
|
||||
vector<uint8_t> elem = dtlss.at(i);
|
||||
EXPECT_TRUE(srs_is_dtls(&elem[0], (size_t)elem.size()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)dtlss.size(); i++) {
|
||||
vector<uint8_t> elem = dtlss.at(i);
|
||||
EXPECT_FALSE(srs_is_dtls(&elem[0], 1));
|
||||
|
||||
// All DTLS should not be other packets.
|
||||
EXPECT_FALSE(srs_is_stun(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_TRUE(srs_is_dtls(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_FALSE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_FALSE(srs_is_rtcp(&elem[0], (size_t)elem.size()));
|
||||
}
|
||||
|
||||
// STUN packet.
|
||||
vector< vector<uint8_t> > stuns;
|
||||
if (true) { uint8_t data[1] = {0}; mock_arr_push(stuns, data); } // binding request.
|
||||
if (true) { uint8_t data[1] = {1}; mock_arr_push(stuns, data); } // binding success response.
|
||||
for (int i = 0; i < (int)stuns.size(); i++) {
|
||||
vector<uint8_t> elem = stuns.at(i);
|
||||
EXPECT_TRUE(srs_is_stun(&elem[0], (size_t)elem.size()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)stuns.size(); i++) {
|
||||
vector<uint8_t> elem = stuns.at(i);
|
||||
EXPECT_FALSE(srs_is_stun(&elem[0], 0));
|
||||
|
||||
// All STUN should not be other packets.
|
||||
EXPECT_TRUE(srs_is_stun(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_FALSE(srs_is_dtls(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_FALSE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_FALSE(srs_is_rtcp(&elem[0], (size_t)elem.size()));
|
||||
}
|
||||
|
||||
// RTCP packet.
|
||||
vector< vector<uint8_t> > rtcps;
|
||||
if (true) { uint8_t data[12] = {0x80, 192}; mock_arr_push(rtcps, data); }
|
||||
if (true) { uint8_t data[12] = {0x80, 200}; mock_arr_push(rtcps, data); } // SR
|
||||
if (true) { uint8_t data[12] = {0x80, 201}; mock_arr_push(rtcps, data); } // RR
|
||||
if (true) { uint8_t data[12] = {0x80, 202}; mock_arr_push(rtcps, data); } // SDES
|
||||
if (true) { uint8_t data[12] = {0x80, 203}; mock_arr_push(rtcps, data); } // BYE
|
||||
if (true) { uint8_t data[12] = {0x80, 204}; mock_arr_push(rtcps, data); } // APP
|
||||
if (true) { uint8_t data[12] = {0x80, 223}; mock_arr_push(rtcps, data); }
|
||||
for (int i = 0; i < (int)rtcps.size(); i++) {
|
||||
vector<uint8_t> elem = rtcps.at(i);
|
||||
EXPECT_TRUE(srs_is_rtcp(&elem[0], (size_t)elem.size()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)rtcps.size(); i++) {
|
||||
vector<uint8_t> elem = rtcps.at(i);
|
||||
EXPECT_FALSE(srs_is_rtcp(&elem[0], 2));
|
||||
|
||||
// All RTCP should not be other packets.
|
||||
EXPECT_FALSE(srs_is_stun(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_FALSE(srs_is_dtls(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_TRUE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_TRUE(srs_is_rtcp(&elem[0], (size_t)elem.size()));
|
||||
}
|
||||
|
||||
// RTP packet.
|
||||
vector< vector<uint8_t> > rtps;
|
||||
if (true) { uint8_t data[12] = {0x80, 96}; mock_arr_push(rtps, data); }
|
||||
if (true) { uint8_t data[12] = {0x80, 127}; mock_arr_push(rtps, data); }
|
||||
if (true) { uint8_t data[12] = {0x80, 224}; mock_arr_push(rtps, data); }
|
||||
if (true) { uint8_t data[12] = {0x80, 255}; mock_arr_push(rtps, data); }
|
||||
for (int i = 0; i < (int)rtps.size(); i++) {
|
||||
vector<uint8_t> elem = rtps.at(i);
|
||||
EXPECT_TRUE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_FALSE(srs_is_rtcp(&elem[0], (size_t)elem.size()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)rtps.size(); i++) {
|
||||
vector<uint8_t> elem = rtps.at(i);
|
||||
EXPECT_FALSE(srs_is_rtp_or_rtcp(&elem[0], 2));
|
||||
|
||||
// All RTP should not be other packets.
|
||||
EXPECT_FALSE(srs_is_stun(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_FALSE(srs_is_dtls(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_TRUE(srs_is_rtp_or_rtcp(&elem[0], (size_t)elem.size()));
|
||||
EXPECT_FALSE(srs_is_rtcp(&elem[0], (size_t)elem.size()));
|
||||
}
|
||||
}
|
||||
|
||||
VOID TEST(KernelRTCTest, DefaultTrackStatus)
|
||||
{
|
||||
// By default, track is disabled.
|
||||
|
|
Loading…
Reference in a new issue