--- Begin Message ---
Classified as: {OPEN}
Hello Ross,
live555 does not provide any means to detect SRTP errors.
>From the user point of view, SRTP errors, mostly SRTP authentication issues,
>are considered as packet losses.
Here is a patch which adds to RTPReceptionStats some statistics about SRTP.
The decrypted SRTP packets with authentication errors are not dropped. Instead,
a counter is incremented which provides information to the user about the
integrity of the received stream. Then, it is up to user to consider or not
the authentication issues.
What do you think?
Yahia
{OPEN}
diff --git a/liveMedia/MultiFramedRTPSource.cpp b/liveMedia/MultiFramedRTPSource.cpp
index a0098a1..cf55660 100644
--- a/liveMedia/MultiFramedRTPSource.cpp
+++ b/liveMedia/MultiFramedRTPSource.cpp
@@ -235,6 +235,7 @@ void MultiFramedRTPSource::networkReadHandler1() {
// Read the network packet, and perform sanity checks on the RTP header:
Boolean readSuccess = False;
+ Boolean processSRTPPacketSuccess = True;
do {
struct sockaddr_storage fromAddress;
Boolean packetReadWasIncomplete = fPacketReadInProgress != NULL;
@@ -258,13 +259,17 @@ void MultiFramedRTPSource::networkReadHandler1() {
if ((our_random()%10) == 0) break; // simulate 10% packet loss
#endif
+#ifdef TEST_SRTP_AUTH
+ if ((our_random()%10) == 0) {
+ u_int8_t* buffer = bPacket->data();
+ buffer[16]++;
+ }
+#endif
if (fCrypto != NULL) { // The packet is SRTP; authenticate/decrypt it first
unsigned newPacketSize;
- if (!fCrypto->processIncomingSRTPPacket(bPacket->data(), bPacket->dataSize(), newPacketSize)) break;
- if (newPacketSize > bPacket->dataSize()) break; // sanity check; shouldn't happen
- bPacket->removePadding(bPacket->dataSize() - newPacketSize); // treat MKI+auth as padding
+ processSRTPPacketSuccess = fCrypto->processIncomingSRTPPacket(bPacket->data(), bPacket->dataSize(), newPacketSize) && (newPacketSize <= bPacket->dataSize());
+ if (processSRTPPacketSuccess) bPacket->removePadding(bPacket->dataSize() - newPacketSize); // treat MKI+auth as padding
}
-
// Check for the 12-byte RTP header:
if (bPacket->dataSize() < 12) break;
unsigned rtpHdr = ntohl(*(u_int32_t*)(bPacket->data())); ADVANCE(4);
@@ -274,7 +279,6 @@ void MultiFramedRTPSource::networkReadHandler1() {
// Check the RTP version number (it should be 2):
if ((rtpHdr&0xC0000000) != 0x80000000) break;
-
// Check the Payload Type.
unsigned char rtpPayloadType = (unsigned char)((rtpHdr&0x007F0000)>>16);
if (rtpPayloadType != rtpPayloadFormat()) {
@@ -319,13 +323,14 @@ void MultiFramedRTPSource::networkReadHandler1() {
fReorderingBuffer->resetHaveSeenFirstPacket();
}
unsigned short rtpSeqNo = (unsigned short)(rtpHdr&0xFFFF);
+
Boolean usableInJitterCalculation
= packetIsUsableInJitterCalculation((bPacket->data()),
bPacket->dataSize());
struct timeval presentationTime; // computed by:
Boolean hasBeenSyncedUsingRTCP; // computed by:
receptionStatsDB()
- .noteIncomingPacket(rtpSSRC, rtpSeqNo, rtpTimestamp,
+ .noteIncomingPacket(rtpSSRC, fCrypto != NULL, processSRTPPacketSuccess, rtpSeqNo, rtpTimestamp,
timestampFrequency(),
usableInJitterCalculation, presentationTime,
hasBeenSyncedUsingRTCP, bPacket->dataSize());
diff --git a/liveMedia/RTCP.cpp b/liveMedia/RTCP.cpp
index becaf72..99b89c2 100644
--- a/liveMedia/RTCP.cpp
+++ b/liveMedia/RTCP.cpp
@@ -592,7 +592,7 @@ void RTCPInstance
if (fSource != NULL) {
RTPReceptionStatsDB& receptionStats
= fSource->receptionStatsDB();
- receptionStats.noteIncomingSR(reportSenderSSRC,
+ receptionStats.noteIncomingSR(reportSenderSSRC, fCrypto != NULL,
NTPmsw, NTPlsw, rtpTimestamp);
}
ADVANCE(8); // skip over packet count, octet count
diff --git a/liveMedia/RTPSource.cpp b/liveMedia/RTPSource.cpp
index bd49d6d..7c3a069 100644
--- a/liveMedia/RTPSource.cpp
+++ b/liveMedia/RTPSource.cpp
@@ -98,7 +98,7 @@ RTPReceptionStatsDB::~RTPReceptionStatsDB() {
}
void RTPReceptionStatsDB
-::noteIncomingPacket(u_int32_t SSRC, u_int16_t seqNum,
+::noteIncomingPacket(u_int32_t SSRC, Boolean useEncryption, Boolean srtpProcessSuccess, u_int16_t seqNum,
u_int32_t rtpTimestamp, unsigned timestampFrequency,
Boolean useForJitterCalculation,
struct timeval& resultPresentationTime,
@@ -109,7 +109,7 @@ void RTPReceptionStatsDB
if (stats == NULL) {
// This is the first time we've heard from this SSRC.
// Create a new record for it:
- stats = new RTPReceptionStats(SSRC, seqNum);
+ stats = new RTPReceptionStats(SSRC, seqNum, useEncryption);
if (stats == NULL) return;
add(SSRC, stats);
}
@@ -118,21 +118,21 @@ void RTPReceptionStatsDB
++fNumActiveSourcesSinceLastReset;
}
- stats->noteIncomingPacket(seqNum, rtpTimestamp, timestampFrequency,
+ stats->noteIncomingPacket(seqNum, srtpProcessSuccess, rtpTimestamp, timestampFrequency,
useForJitterCalculation,
resultPresentationTime,
resultHasBeenSyncedUsingRTCP, packetSize);
}
void RTPReceptionStatsDB
-::noteIncomingSR(u_int32_t SSRC,
+::noteIncomingSR(u_int32_t SSRC, Boolean useEncryption,
u_int32_t ntpTimestampMSW, u_int32_t ntpTimestampLSW,
u_int32_t rtpTimestamp) {
RTPReceptionStats* stats = lookup(SSRC);
if (stats == NULL) {
// This is the first time we've heard of this SSRC.
// Create a new record for it:
- stats = new RTPReceptionStats(SSRC);
+ stats = new RTPReceptionStats(SSRC, useEncryption);
if (stats == NULL) return;
add(SSRC, stats);
}
@@ -185,21 +185,25 @@ void RTPReceptionStatsDB::add(u_int32_t SSRC, RTPReceptionStats* stats) {
////////// RTPReceptionStats //////////
-RTPReceptionStats::RTPReceptionStats(u_int32_t SSRC, u_int16_t initialSeqNum) {
+RTPReceptionStats::RTPReceptionStats(u_int32_t SSRC, Boolean useEncryption, u_int16_t initialSeqNum) {
initSeqNum(initialSeqNum);
- init(SSRC);
+ init(SSRC, useEncryption);
}
-RTPReceptionStats::RTPReceptionStats(u_int32_t SSRC) {
- init(SSRC);
+RTPReceptionStats::RTPReceptionStats(u_int32_t SSRC, Boolean useEncryption) {
+ init(SSRC, useEncryption);
}
RTPReceptionStats::~RTPReceptionStats() {
}
-void RTPReceptionStats::init(u_int32_t SSRC) {
+void RTPReceptionStats::init(u_int32_t SSRC, Boolean useEncryption) {
fSSRC = SSRC;
+ fUseEncryption=useEncryption;
fTotNumPacketsReceived = 0;
+ fNumPacketsReceivedSinceLastReset = 0;
+ fTotNumSRTPErrors = 0;
+ fNumSRTPErrorsSinceLastReset = 0;
fTotBytesReceived_hi = fTotBytesReceived_lo = 0;
fBaseExtSeqNumReceived = 0;
fHighestExtSeqNumReceived = 0;
@@ -229,7 +233,7 @@ void RTPReceptionStats::initSeqNum(u_int16_t initialSeqNum) {
#endif
void RTPReceptionStats
-::noteIncomingPacket(u_int16_t seqNum, u_int32_t rtpTimestamp,
+::noteIncomingPacket(u_int16_t seqNum, Boolean srtpProcessSuccess, u_int32_t rtpTimestamp,
unsigned timestampFrequency,
Boolean useForJitterCalculation,
struct timeval& resultPresentationTime,
@@ -239,6 +243,11 @@ void RTPReceptionStats
++fNumPacketsReceivedSinceLastReset;
++fTotNumPacketsReceived;
+ if (!srtpProcessSuccess && fUseEncryption)
+ {
+ ++fNumSRTPErrorsSinceLastReset;
+ ++fTotNumSRTPErrors;
+ }
u_int32_t prevTotBytesReceived_lo = fTotBytesReceived_lo;
fTotBytesReceived_lo += packetSize;
if (fTotBytesReceived_lo < prevTotBytesReceived_lo) { // wrap-around
@@ -393,6 +402,7 @@ unsigned RTPReceptionStats::jitter() const {
void RTPReceptionStats::reset() {
fNumPacketsReceivedSinceLastReset = 0;
+ fNumSRTPErrorsSinceLastReset = 0;
fLastResetExtSeqNumReceived = fHighestExtSeqNumReceived;
}
diff --git a/liveMedia/SRTPCryptographicContext.cpp b/liveMedia/SRTPCryptographicContext.cpp
index 37a4994..0ba3c78 100644
--- a/liveMedia/SRTPCryptographicContext.cpp
+++ b/liveMedia/SRTPCryptographicContext.cpp
@@ -76,6 +76,7 @@ Boolean SRTPCryptographicContext
// First time:
nextROC = thisPacketsROC = fReceptionROC = fMIKEYState.initialROC();
nextHighRTPSeqNum = rtpSeqNum;
+
} else {
// Check whether the sequence number has rolled over, or is out-of-order:
u_int16_t const SEQ_NUM_THRESHOLD = 0x1000;
diff --git a/liveMedia/include/RTPSource.hh b/liveMedia/include/RTPSource.hh
index d17db7c..a658de1 100644
--- a/liveMedia/include/RTPSource.hh
+++ b/liveMedia/include/RTPSource.hh
@@ -146,7 +146,7 @@ public:
};
// The following is called whenever a RTP packet is received:
- void noteIncomingPacket(u_int32_t SSRC, u_int16_t seqNum,
+ void noteIncomingPacket(u_int32_t SSRC, Boolean useEncryption, Boolean srtpError, u_int16_t seqNum,
u_int32_t rtpTimestamp,
unsigned timestampFrequency,
Boolean useForJitterCalculation,
@@ -155,7 +155,7 @@ public:
unsigned packetSize /* payload only */);
// The following is called whenever a RTCP SR packet is received:
- void noteIncomingSR(u_int32_t SSRC,
+ void noteIncomingSR(u_int32_t SSRC, Boolean useEncryption,
u_int32_t ntpTimestampMSW, u_int32_t ntpTimestampLSW,
u_int32_t rtpTimestamp);
@@ -184,12 +184,18 @@ private:
class RTPReceptionStats {
public:
u_int32_t SSRC() const { return fSSRC; }
+ Boolean useEncyption() const { return fUseEncryption; }
unsigned numPacketsReceivedSinceLastReset() const {
return fNumPacketsReceivedSinceLastReset;
}
unsigned totNumPacketsReceived() const { return fTotNumPacketsReceived; }
double totNumKBytesReceived() const;
+ unsigned numSRTPErrorsSinceLastReset() const {
+ return fNumSRTPErrorsSinceLastReset;
+ }
+ unsigned totNumSRTPErrors() const { return fTotNumSRTPErrors; }
+
unsigned totNumPacketsExpected() const {
return (fHighestExtSeqNumReceived - fBaseExtSeqNumReceived) + 1;
}
@@ -219,12 +225,12 @@ public:
protected:
// called only by RTPReceptionStatsDB:
friend class RTPReceptionStatsDB;
- RTPReceptionStats(u_int32_t SSRC, u_int16_t initialSeqNum);
- RTPReceptionStats(u_int32_t SSRC);
+ RTPReceptionStats(u_int32_t SSRC, Boolean useEncryption );
+ RTPReceptionStats(u_int32_t SSRC, Boolean useEncryption, u_int16_t initialSeqNum );
virtual ~RTPReceptionStats();
private:
- void noteIncomingPacket(u_int16_t seqNum, u_int32_t rtpTimestamp,
+ void noteIncomingPacket(u_int16_t seqNum, Boolean srtpProcessSuccess, u_int32_t rtpTimestamp,
unsigned timestampFrequency,
Boolean useForJitterCalculation,
struct timeval& resultPresentationTime,
@@ -232,7 +238,7 @@ private:
unsigned packetSize /* payload only */);
void noteIncomingSR(u_int32_t ntpTimestampMSW, u_int32_t ntpTimestampLSW,
u_int32_t rtpTimestamp);
- void init(u_int32_t SSRC);
+ void init(u_int32_t SSRC, Boolean useEncryption);
void initSeqNum(u_int16_t initialSeqNum);
void reset();
// resets periodic stats (called each time they're used to
@@ -240,8 +246,11 @@ private:
protected:
u_int32_t fSSRC;
+ Boolean fUseEncryption;
unsigned fNumPacketsReceivedSinceLastReset;
unsigned fTotNumPacketsReceived;
+ unsigned fNumSRTPErrorsSinceLastReset;
+ unsigned fTotNumSRTPErrors;
u_int32_t fTotBytesReceived_hi, fTotBytesReceived_lo;
Boolean fHaveSeenInitialSequenceNumber;
unsigned fBaseExtSeqNumReceived;
--- End Message ---