Merge pull request #145 from Strilanc/audio_stampery

Setting timestamp based on number of samples sent
pull/1/head
Frederic Jacobs 11 years ago
commit 54043cd80d

@ -20,6 +20,7 @@
@interface AudioPacker : NSObject { @interface AudioPacker : NSObject {
@private NSMutableArray* framesToSend; @private NSMutableArray* framesToSend;
@private uint16_t nextSequenceNumber; @private uint16_t nextSequenceNumber;
@private uint32_t nextTimeStamp;
@private Queue* audioFrameToReceiveQueue; @private Queue* audioFrameToReceiveQueue;
} }

@ -9,6 +9,7 @@
AudioPacker* newAudioPackerInstance = [AudioPacker new]; AudioPacker* newAudioPackerInstance = [AudioPacker new];
newAudioPackerInstance->audioFrameToReceiveQueue = [Queue new]; newAudioPackerInstance->audioFrameToReceiveQueue = [Queue new];
newAudioPackerInstance->framesToSend = [NSMutableArray array]; newAudioPackerInstance->framesToSend = [NSMutableArray array];
newAudioPackerInstance->nextTimeStamp = [CryptoTools generateSecureRandomUInt32];
newAudioPackerInstance->nextSequenceNumber = [CryptoTools generateSecureRandomUInt16]; newAudioPackerInstance->nextSequenceNumber = [CryptoTools generateSecureRandomUInt16];
// interop fix: // interop fix:
@ -29,10 +30,13 @@
if (framesToSend.count < AUDIO_FRAMES_PER_PACKET) return nil; if (framesToSend.count < AUDIO_FRAMES_PER_PACKET) return nil;
uint16_t sequenceNumber = nextSequenceNumber++; uint16_t sequenceNumber = nextSequenceNumber++;
NSData* payload = [framesToSend concatDatas]; uint32_t timeStamp = nextTimeStamp;
NSData* payload = framesToSend.concatDatas;
nextTimeStamp += payload.length;
[framesToSend removeAllObjects]; [framesToSend removeAllObjects];
return [EncodedAudioPacket encodedAudioPacketWithAudioData:payload return [EncodedAudioPacket encodedAudioPacketWithAudioData:payload
andTimeStamp:timeStamp
andSequenceNumber:sequenceNumber]; andSequenceNumber:sequenceNumber];
} }

@ -19,19 +19,21 @@
PacketHandlerBlock valueHandler = ^(RtpPacket* rtpPacket) { PacketHandlerBlock valueHandler = ^(RtpPacket* rtpPacket) {
require(rtpPacket != nil); require(rtpPacket != nil);
require([rtpPacket isKindOfClass:[RtpPacket class]]); require([rtpPacket isKindOfClass:[RtpPacket class]]);
[handler handlePacket:[EncodedAudioPacket encodedAudioPacketWithAudioData:[rtpPacket payload] [handler handlePacket:[EncodedAudioPacket encodedAudioPacketWithAudioData:rtpPacket.payload
andSequenceNumber:[rtpPacket sequenceNumber]]]; andTimeStamp:rtpPacket.timeStamp
andSequenceNumber:rtpPacket.sequenceNumber]];
}; };
[srtpSocket startWithHandler:[PacketHandler packetHandler:valueHandler [srtpSocket startWithHandler:[PacketHandler packetHandler:valueHandler
withErrorHandler:[handler errorHandler]] withErrorHandler:handler.errorHandler]
untilCancelled:untilCancelledToken]; untilCancelled:untilCancelledToken];
} }
-(void) send:(EncodedAudioPacket*)audioPacket { -(void) send:(EncodedAudioPacket*)audioPacket {
require(audioPacket != nil); require(audioPacket != nil);
RtpPacket* rtpPacket = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:[audioPacket sequenceNumber] RtpPacket* rtpPacket = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:audioPacket.sequenceNumber
andPayload:[audioPacket audioData]]; andTimeStamp:audioPacket.timeStamp
andPayload:audioPacket.audioData];
[srtpSocket secureAndSendRtpPacket:rtpPacket]; [srtpSocket secureAndSendRtpPacket:rtpPacket];
} }

@ -12,8 +12,11 @@
@interface EncodedAudioPacket : NSObject @interface EncodedAudioPacket : NSObject
@property (readonly,nonatomic) NSData* audioData; @property (readonly,nonatomic) NSData* audioData;
@property (readonly,nonatomic) uint32_t timeStamp;
@property (readonly,nonatomic) uint16_t sequenceNumber; @property (readonly,nonatomic) uint16_t sequenceNumber;
+(EncodedAudioPacket*) encodedAudioPacketWithAudioData:(NSData*)audioData andSequenceNumber:(uint16_t)sequenceNumber; +(EncodedAudioPacket*) encodedAudioPacketWithAudioData:(NSData*)audioData
andTimeStamp:(uint32_t)timeStamp
andSequenceNumber:(uint16_t)sequenceNumber;
@end @end

@ -5,10 +5,13 @@
@synthesize audioData, sequenceNumber; @synthesize audioData, sequenceNumber;
+(EncodedAudioPacket*) encodedAudioPacketWithAudioData:(NSData*)audioData andSequenceNumber:(uint16_t)sequenceNumber { +(EncodedAudioPacket*) encodedAudioPacketWithAudioData:(NSData*)audioData
andTimeStamp:(uint32_t)timeStamp
andSequenceNumber:(uint16_t)sequenceNumber {
require(audioData != nil); require(audioData != nil);
EncodedAudioPacket* p = [EncodedAudioPacket new]; EncodedAudioPacket* p = [EncodedAudioPacket new];
p->audioData = audioData; p->audioData = audioData;
p->_timeStamp = timeStamp; // Not sure why timeStamp gets a leading underscore but the others don't; probably a reserved name?
p->sequenceNumber = sequenceNumber; p->sequenceNumber = sequenceNumber;
return p; return p;
} }

@ -8,6 +8,9 @@
/// Returns a secure random 16-bit unsigned integer. /// Returns a secure random 16-bit unsigned integer.
+(uint16_t)generateSecureRandomUInt16; +(uint16_t)generateSecureRandomUInt16;
/// Returns a secure random 32-bit unsigned integer.
+(uint32_t)generateSecureRandomUInt32;
/// Returns data composed of 'length' cryptographically unpredictable bytes sampled uniformly from [0, 256). /// Returns data composed of 'length' cryptographically unpredictable bytes sampled uniformly from [0, 256).
+(NSData*)generateSecureRandomData:(NSUInteger)length; +(NSData*)generateSecureRandomData:(NSUInteger)length;

@ -20,6 +20,10 @@
return [[self generateSecureRandomData:sizeof(uint16_t)] bigEndianUInt16At:0]; return [[self generateSecureRandomData:sizeof(uint16_t)] bigEndianUInt16At:0];
} }
+(uint32_t)generateSecureRandomUInt32 {
return [[self generateSecureRandomData:sizeof(uint32_t)] bigEndianUInt32At:0];
}
+(NSString*) computeOtpWithPassword:(NSString*)password andCounter:(int64_t)counter { +(NSString*) computeOtpWithPassword:(NSString*)password andCounter:(int64_t)counter {
require(password != nil); require(password != nil);

@ -26,7 +26,9 @@
@property (nonatomic,readonly) uint32_t synchronizationSourceIdentifier; @property (nonatomic,readonly) uint32_t synchronizationSourceIdentifier;
@property (nonatomic,readonly) NSData* payload; @property (nonatomic,readonly) NSData* payload;
+(RtpPacket*) rtpPacketWithDefaultsAndSequenceNumber:(uint16_t)sequenceNumber andPayload:(NSData*)payload; +(RtpPacket*) rtpPacketWithDefaultsAndSequenceNumber:(uint16_t)sequenceNumber
andTimeStamp:(uint32_t)timeStamp
andPayload:(NSData *)payload;
+(RtpPacket*) rtpPacketWithVersion:(uint8_t)version +(RtpPacket*) rtpPacketWithVersion:(uint8_t)version
andPadding:(uint8_t)padding andPadding:(uint8_t)padding

@ -42,7 +42,9 @@ const uint8_t PACKET_VERSION = 2;
@synthesize version; @synthesize version;
@synthesize wasAdjustedDueToInteropIssues; @synthesize wasAdjustedDueToInteropIssues;
+(RtpPacket*) rtpPacketWithDefaultsAndSequenceNumber:(uint16_t)sequenceNumber andPayload:(NSData *)payload { +(RtpPacket*) rtpPacketWithDefaultsAndSequenceNumber:(uint16_t)sequenceNumber
andTimeStamp:(uint32_t)timeStamp
andPayload:(NSData *)payload {
require(payload != nil); require(payload != nil);
return [RtpPacket rtpPacketWithVersion:PACKET_VERSION return [RtpPacket rtpPacketWithVersion:PACKET_VERSION
andPadding:0 andPadding:0
@ -51,7 +53,7 @@ const uint8_t PACKET_VERSION = 2;
andMarkerBit:false andMarkerBit:false
andPayloadtype:0 andPayloadtype:0
andSequenceNumber:sequenceNumber andSequenceNumber:sequenceNumber
andTimeStamp:0 andTimeStamp:timeStamp
andPayload:payload]; andPayload:payload];
} }
+(RtpPacket*) rtpPacketWithVersion:(uint8_t)version +(RtpPacket*) rtpPacketWithVersion:(uint8_t)version
@ -340,7 +342,9 @@ andSynchronizationSourceIdentifier:(uint32_t)synchronizedSourceIdentifier
return extensionHeaderData; return extensionHeaderData;
} }
-(NSData*) rawPacketDataUsingInteropOptions:(NSArray*)interopOptions { -(NSData*) rawPacketDataUsingInteropOptions:(NSArray*)interopOptions {
if (rawPacketData == nil) rawPacketData = [self generateSerializedPacketDataUsingInteropOptions:interopOptions]; if (rawPacketData == nil) {
rawPacketData = [self generateSerializedPacketDataUsingInteropOptions:interopOptions];
}
return rawPacketData; return rawPacketData;
} }
-(bool) isEqualToRtpPacket:(RtpPacket*)other { -(bool) isEqualToRtpPacket:(RtpPacket*)other {

@ -10,9 +10,14 @@
-(void) testTrivial { -(void) testTrivial {
NSData* d2 = [NSMutableData dataWithLength:6]; NSData* d2 = [NSMutableData dataWithLength:6];
testThrows([EncodedAudioPacket encodedAudioPacketWithAudioData:nil andSequenceNumber:0]); testThrows([EncodedAudioPacket encodedAudioPacketWithAudioData:nil
EncodedAudioPacket* p2 = [EncodedAudioPacket encodedAudioPacketWithAudioData:d2 andSequenceNumber:0xFF00]; andTimeStamp:0
test([p2 audioData] == d2); andSequenceNumber:0]);
test([p2 sequenceNumber] == 0xFF00); EncodedAudioPacket* p2 = [EncodedAudioPacket encodedAudioPacketWithAudioData:d2
andTimeStamp:0x23571113
andSequenceNumber:0xFF00];
test(p2.audioData == d2);
test(p2.timeStamp == 0x23571113);
test(p2.sequenceNumber == 0xFF00);
} }
@end @end

@ -15,6 +15,8 @@
#define testLoggedDiscard(q, sequenceNumber, oldReadHeadSequenceNumber, newReadHeadSequenceNumber) testLogged(q, ([NSString stringWithFormat:@"discard %d,%d,%d", sequenceNumber, oldReadHeadSequenceNumber, newReadHeadSequenceNumber])) #define testLoggedDiscard(q, sequenceNumber, oldReadHeadSequenceNumber, newReadHeadSequenceNumber) testLogged(q, ([NSString stringWithFormat:@"discard %d,%d,%d", sequenceNumber, oldReadHeadSequenceNumber, newReadHeadSequenceNumber]))
#define testLoggedResync(q, oldReadHeadSequenceNumber, newReadHeadSequenceNumber) testLogged(q, ([NSString stringWithFormat:@"resync %d to %d", oldReadHeadSequenceNumber,newReadHeadSequenceNumber])) #define testLoggedResync(q, oldReadHeadSequenceNumber, newReadHeadSequenceNumber) testLogged(q, ([NSString stringWithFormat:@"resync %d to %d", oldReadHeadSequenceNumber,newReadHeadSequenceNumber]))
#define TICK 320
@interface JitterQueueTest : XCTestCase @interface JitterQueueTest : XCTestCase
@end @end
@ -24,14 +26,18 @@
JitterQueue* r1 = [JitterQueue jitterQueue]; JitterQueue* r1 = [JitterQueue jitterQueue];
JitterQueue* r2 = [JitterQueue jitterQueue]; JitterQueue* r2 = [JitterQueue jitterQueue];
EncodedAudioPacket* q1 = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:100]; EncodedAudioPacket* q1 = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:100*TICK
andSequenceNumber:100];
test(r1.count == 0); test(r1.count == 0);
test([r1 tryEnqueue:q1]); test([r1 tryEnqueue:q1]);
test(r1.count == 1); test(r1.count == 1);
test([r1 tryDequeue] == q1); test([r1 tryDequeue] == q1);
test(r1.count == 0); test(r1.count == 0);
EncodedAudioPacket* q2 = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0xFF00]; EncodedAudioPacket* q2 = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:0xFF00*TICK
andSequenceNumber:0xFF00];
test(r2.count == 0); test(r2.count == 0);
test([r2 tryEnqueue:q2]); test([r2 tryEnqueue:q2]);
test(r2.count == 1); test(r2.count == 1);
@ -42,7 +48,9 @@
JitterQueue* r = [JitterQueue jitterQueue]; JitterQueue* r = [JitterQueue jitterQueue];
for (uint16_t i = 0; i < 10; i++) { for (uint16_t i = 0; i < 10; i++) {
EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:i]; EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:i*TICK
andSequenceNumber:i];
test([r tryEnqueue:q]); test([r tryEnqueue:q]);
test(r.count == i+1); test(r.count == i+1);
} }
@ -57,7 +65,9 @@
JitterQueue* r = [JitterQueue jitterQueue]; JitterQueue* r = [JitterQueue jitterQueue];
for (uint16_t i = 0; i < 10; i++) { for (uint16_t i = 0; i < 10; i++) {
EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:i*2+1]; EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:(i*2+1)*TICK
andSequenceNumber:i*2+1];
test([r tryEnqueue:q]); test([r tryEnqueue:q]);
} }
@ -73,7 +83,9 @@
for (uint16_t i = 0; i < 20; i++) { for (uint16_t i = 0; i < 20; i++) {
for (uint16_t j = 0; j < 2; j++) { for (uint16_t j = 0; j < 2; j++) {
EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:i*2+j]; EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:(i*2+j)*TICK
andSequenceNumber:i*2+j];
test([r tryEnqueue:q]); test([r tryEnqueue:q]);
} }
@ -84,11 +96,15 @@
-(void) testJitterQueueRejectsDuplicateSequenceNumbers { -(void) testJitterQueueRejectsDuplicateSequenceNumbers {
JitterQueue* r = [JitterQueue jitterQueue]; JitterQueue* r = [JitterQueue jitterQueue];
EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0]; EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:0
andSequenceNumber:0];
test([r tryEnqueue:p]); test([r tryEnqueue:p]);
for (uint16_t i = 0; i < 10; i++) { for (uint16_t i = 0; i < 10; i++) {
EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0]; EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:0
andSequenceNumber:0];
test(![r tryEnqueue:q]); test(![r tryEnqueue:q]);
} }
@ -98,11 +114,15 @@
-(void) testJitterQueueRejectsOldSequenceNumbers { -(void) testJitterQueueRejectsOldSequenceNumbers {
JitterQueue* r = [JitterQueue jitterQueue]; JitterQueue* r = [JitterQueue jitterQueue];
EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:50]; EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:50*TICK
andSequenceNumber:50];
test([r tryEnqueue:p]); test([r tryEnqueue:p]);
for (uint16_t i = 1; i < 10; i++) { for (uint16_t i = 1; i < 10; i++) {
EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:50 - i]; EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:(50-i)*TICK
andSequenceNumber:50 - i];
test(![r tryEnqueue:q]); test(![r tryEnqueue:q]);
} }
@ -112,11 +132,15 @@
-(void) testJitterQueueRejectsFarOffSequenceNumbers { -(void) testJitterQueueRejectsFarOffSequenceNumbers {
JitterQueue* r = [JitterQueue jitterQueue]; JitterQueue* r = [JitterQueue jitterQueue];
EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0]; EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:0
andSequenceNumber:0];
test([r tryEnqueue:p]); test([r tryEnqueue:p]);
for (uint16_t i = 0; i < 10; i++) { for (uint16_t i = 0; i < 10; i++) {
EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0x7000+i]; EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:(0x7000+i)*TICK
andSequenceNumber:0x7000+i];
test(![r tryEnqueue:q]); test(![r tryEnqueue:q]);
} }
@ -126,11 +150,15 @@
-(void) testJitterQueueResyncsSequenceNumber { -(void) testJitterQueueResyncsSequenceNumber {
JitterQueue* r = [JitterQueue jitterQueue]; JitterQueue* r = [JitterQueue jitterQueue];
EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:1]; EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:1*TICK
andSequenceNumber:1];
test([r tryEnqueue:p]); test([r tryEnqueue:p]);
test([r tryDequeue] == p); test([r tryDequeue] == p);
EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0]; EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:0
andSequenceNumber:0];
test(![r tryEnqueue:q]); test(![r tryEnqueue:q]);
// cause desync to be detected // cause desync to be detected
@ -142,11 +170,25 @@
test([r tryEnqueue:q]); test([r tryEnqueue:q]);
test([r tryDequeue] == q); test([r tryDequeue] == q);
} }
-(void) testLoopAround { -(void) testLoopAround_sequenceNumber {
JitterQueue* r = [JitterQueue jitterQueue];
for (uint32_t i = 0; i < 1 << 17; i++) {
EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:i*TICK
andSequenceNumber:(uint16_t)(i & 0xFFFF)];
test([r tryEnqueue:q]);
test([r tryDequeue] == q);
}
test([r tryDequeue] == nil);
}
-(void) testLoopAround_timeStamp {
JitterQueue* r = [JitterQueue jitterQueue]; JitterQueue* r = [JitterQueue jitterQueue];
for (int i = 0; i < 1 << 17; i++) { for (uint32_t i = 0; i < 1 << 17; i++) {
EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:(uint16_t)(i & 0xFFFF)]; EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1]
andTimeStamp:i*TICK + 0xFFFF0000
andSequenceNumber:(uint16_t)(i & 0xFFFF)];
test([r tryEnqueue:q]); test([r tryEnqueue:q]);
test([r tryDequeue] == q); test([r tryDequeue] == q);
} }
@ -154,15 +196,21 @@
} }
-(void) testJitterQueueAvoidsRacingAhead { -(void) testJitterQueueAvoidsRacingAhead {
JitterQueue* r = [JitterQueue jitterQueue]; JitterQueue* r = [JitterQueue jitterQueue];
EncodedAudioPacket* p1 = [EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(1) andSequenceNumber:0]; EncodedAudioPacket* p1 = [EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(1)
EncodedAudioPacket* p2 = [EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(1) andSequenceNumber:1]; andTimeStamp:0
andSequenceNumber:0];
EncodedAudioPacket* p2 = [EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(1)
andTimeStamp:1*TICK
andSequenceNumber:1];
test([r tryEnqueue:p1]); test([r tryEnqueue:p1]);
test([r tryDequeue] == p1); test([r tryDequeue] == p1);
test([r tryDequeue] == nil); test([r tryDequeue] == nil);
test([r tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(1) andSequenceNumber:10]]); test([r tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(1)
andTimeStamp:10*TICK
andSequenceNumber:10]]);
test([r tryDequeue] == nil); test([r tryDequeue] == nil);
test([r tryEnqueue:p2]); test([r tryEnqueue:p2]);
@ -173,11 +221,17 @@
-(void) testJitterQueueMeasurement { -(void) testJitterQueueMeasurement {
JitterQueue* q = [JitterQueue jitterQueue]; JitterQueue* q = [JitterQueue jitterQueue];
[q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:1]]; [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20)
andTimeStamp:1*TICK
andSequenceNumber:1]];
test([q currentBufferDepth] == 0); test([q currentBufferDepth] == 0);
[q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:2]]; [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20)
andTimeStamp:2*TICK
andSequenceNumber:2]];
test([q currentBufferDepth] == 1); test([q currentBufferDepth] == 1);
[q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:4]]; [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20)
andTimeStamp:4*TICK
andSequenceNumber:4]];
test([q currentBufferDepth] == 3); test([q currentBufferDepth] == 3);
[q tryDequeue]; [q tryDequeue];
test([q currentBufferDepth] == 2); test([q currentBufferDepth] == 2);
@ -187,14 +241,18 @@
test([q currentBufferDepth] == 0); test([q currentBufferDepth] == 0);
[q tryDequeue]; [q tryDequeue];
test([q currentBufferDepth] == -1); test([q currentBufferDepth] == -1);
[q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:8]]; [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20)
andTimeStamp:8*TICK
andSequenceNumber:8]];
test([q currentBufferDepth] == 3); test([q currentBufferDepth] == 3);
// resyncs to 0 // resyncs to 0
for (int i = 0; i < 500; i++) { for (int i = 0; i < 500; i++) {
[q tryDequeue]; [q tryDequeue];
} }
[q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:9000]]; [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20)
andTimeStamp:9000*TICK
andSequenceNumber:9000]];
test([q currentBufferDepth] == 0); test([q currentBufferDepth] == 0);
} }
@end @end

@ -20,7 +20,7 @@
andMarkerBit:false andMarkerBit:false
andPayloadtype:0 andPayloadtype:0
andSequenceNumber:5 andSequenceNumber:5
andTimeStamp:0 andTimeStamp:0x23571113
andPayload:increasingData(5)]; andPayload:increasingData(5)];
// values were retained // values were retained
@ -32,23 +32,27 @@
test(r.isMarkerBitSet == false); test(r.isMarkerBitSet == false);
test([r payloadType] == 0); test([r payloadType] == 0);
test([r sequenceNumber] == 5); test([r sequenceNumber] == 5);
test([r timeStamp] == 0); test([r timeStamp] == 0x23571113);
test([[r payload] isEqualToData:increasingData(5)]); test([[r payload] isEqualToData:increasingData(5)]);
// equivalent to simplified constructor // equivalent to simplified constructor
test([r isEqualToRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:5 andPayload:increasingData(5)]]); test([r isEqualToRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:5
andTimeStamp:0x23571113
andPayload:increasingData(5)]]);
// packed correctly // packed correctly
NSData* expectedData = [@[ NSData* expectedData = [@[
@0x80,@0,@0,@5, @0x80,@0,@0,@5,
@0,@0,@0,@0, @0x23,@0x57,@0x11,@0x13,
@0,@0,@0,@0, @0,@0,@0,@0,
@0,@1,@2,@3,@4] toUint8Data]; @0,@1,@2,@3,@4] toUint8Data];
test([[r rawPacketDataUsingInteropOptions:@[]] isEqualToData:expectedData]); test([[r rawPacketDataUsingInteropOptions:@[]] isEqualToData:expectedData]);
// reparsing packed data gives same packet // reparsing packed data gives same packet
test([r isEqualToRtpPacket:[RtpPacket rtpPacketParsedFromPacketData:expectedData]]); test([r isEqualToRtpPacket:[RtpPacket rtpPacketParsedFromPacketData:expectedData]]);
test(![r isEqualToRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0 andPayload:[NSData data]]]); test(![r isEqualToRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0
andTimeStamp:0
andPayload:[NSData data]]]);
} }
-(void) testRawData { -(void) testRawData {
RtpPacket* r = [RtpPacket rtpPacketWithVersion:2 RtpPacket* r = [RtpPacket rtpPacketWithVersion:2
@ -84,7 +88,9 @@
test([[r rawPacketDataUsingInteropOptions:@[]] isEqualToData:expectedData]); test([[r rawPacketDataUsingInteropOptions:@[]] isEqualToData:expectedData]);
test([r isEqualToRtpPacket:[RtpPacket rtpPacketParsedFromPacketData:expectedData]]); test([r isEqualToRtpPacket:[RtpPacket rtpPacketParsedFromPacketData:expectedData]]);
test(![r isEqualToRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:90 andPayload:[NSData data]]]); test(![r isEqualToRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:90
andTimeStamp:0
andPayload:[NSData data]]]);
} }
-(void) testExtendedData { -(void) testExtendedData {
RtpPacket* r = [RtpPacket rtpPacketWithVersion:2 RtpPacket* r = [RtpPacket rtpPacketWithVersion:2
@ -123,7 +129,9 @@
@0,@1,@2,@3,@4] toUint8Data]; @0,@1,@2,@3,@4] toUint8Data];
test([[r rawPacketDataUsingInteropOptions:@[]] isEqualToData:expectedData]); test([[r rawPacketDataUsingInteropOptions:@[]] isEqualToData:expectedData]);
test([r isEqualToRtpPacket:[RtpPacket rtpPacketParsedFromPacketData:expectedData]]); test([r isEqualToRtpPacket:[RtpPacket rtpPacketParsedFromPacketData:expectedData]]);
test(![r isEqualToRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0 andPayload:[NSData data]]]); test(![r isEqualToRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0
andTimeStamp:0
andPayload:[NSData data]]]);
} }
@end @end

@ -21,7 +21,9 @@
SrtpStream* ss = [SrtpStream srtpStreamWithCipherKey:key andMacKey:macKey andCipherIvSalt:salt]; SrtpStream* ss = [SrtpStream srtpStreamWithCipherKey:key andMacKey:macKey andCipherIvSalt:salt];
for (uint64_t sequenceNumber = 0; sequenceNumber < 0x70000; sequenceNumber += 0x7000) { for (uint64_t sequenceNumber = 0; sequenceNumber < 0x70000; sequenceNumber += 0x7000) {
RtpPacket* r = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:(uint16_t)(sequenceNumber & 0xFFFF) andPayload:generatePseudoRandomData(12)]; RtpPacket* r = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:(uint16_t)(sequenceNumber & 0xFFFF)
andTimeStamp:(uint32_t)(sequenceNumber * 320)
andPayload:generatePseudoRandomData(12)];
RtpPacket* s = [ss encryptAndAuthenticateNormalRtpPacket:r]; RtpPacket* s = [ss encryptAndAuthenticateNormalRtpPacket:r];
RtpPacket* r2 = [ss verifyAuthenticationAndDecryptSecuredRtpPacket:s]; RtpPacket* r2 = [ss verifyAuthenticationAndDecryptSecuredRtpPacket:s];
test(![r isEqualToRtpPacket:s]); test(![r isEqualToRtpPacket:s]);
@ -36,12 +38,20 @@
SrtpStream* ss = [SrtpStream srtpStreamWithCipherKey:key andMacKey:macKey andCipherIvSalt:salt]; SrtpStream* ss = [SrtpStream srtpStreamWithCipherKey:key andMacKey:macKey andCipherIvSalt:salt];
// fuzzing // fuzzing
testThrows([ss verifyAuthenticationAndDecryptSecuredRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0 andPayload:generatePseudoRandomData(0)]]); testThrows([ss verifyAuthenticationAndDecryptSecuredRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0
testThrows([ss verifyAuthenticationAndDecryptSecuredRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0 andPayload:generatePseudoRandomData(12)]]); andTimeStamp:0
testThrows([ss verifyAuthenticationAndDecryptSecuredRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0 andPayload:generatePseudoRandomData(100)]]); andPayload:generatePseudoRandomData(0)]]);
testThrows([ss verifyAuthenticationAndDecryptSecuredRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0
andTimeStamp:0
andPayload:generatePseudoRandomData(12)]]);
testThrows([ss verifyAuthenticationAndDecryptSecuredRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:0
andTimeStamp:0
andPayload:generatePseudoRandomData(100)]]);
// authenticated then bit flip // authenticated then bit flip
RtpPacket* r = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:5 andPayload:generatePseudoRandomData(40)]; RtpPacket* r = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:5
andTimeStamp:320*5
andPayload:generatePseudoRandomData(40)];
RtpPacket* s = [ss encryptAndAuthenticateNormalRtpPacket:r]; RtpPacket* s = [ss encryptAndAuthenticateNormalRtpPacket:r];
NSMutableData* m = [[s payload] mutableCopy]; NSMutableData* m = [[s payload] mutableCopy];
[m setUint8At:0 to:[m uint8At:0]^1]; [m setUint8At:0 to:[m uint8At:0]^1];
@ -57,11 +67,15 @@
SrtpStream* s2 = [SrtpStream srtpStreamWithCipherKey:key andMacKey:macKey andCipherIvSalt:salt]; SrtpStream* s2 = [SrtpStream srtpStreamWithCipherKey:key andMacKey:macKey andCipherIvSalt:salt];
for (NSUInteger i = 0; i < 0x20000; i+= 0x100) { for (NSUInteger i = 0; i < 0x20000; i+= 0x100) {
RtpPacket* m = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:(uint16_t)(i & 0xFFFF) andPayload:generatePseudoRandomData(40)]; RtpPacket* m = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:(uint16_t)(i & 0xFFFF)
andTimeStamp:(uint32_t)(i*320 + 5)
andPayload:generatePseudoRandomData(40)];
testThrows([s1 verifyAuthenticationAndDecryptSecuredRtpPacket:m]); testThrows([s1 verifyAuthenticationAndDecryptSecuredRtpPacket:m]);
} }
RtpPacket* r = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:5 andPayload:generatePseudoRandomData(40)]; RtpPacket* r = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:5
andTimeStamp:5*320 + 5
andPayload:generatePseudoRandomData(40)];
RtpPacket* s = [s2 encryptAndAuthenticateNormalRtpPacket:r]; RtpPacket* s = [s2 encryptAndAuthenticateNormalRtpPacket:r];
RtpPacket* r2 = [s1 verifyAuthenticationAndDecryptSecuredRtpPacket:s]; RtpPacket* r2 = [s1 verifyAuthenticationAndDecryptSecuredRtpPacket:s];
test([r isEqualToRtpPacket:r2]); test([r isEqualToRtpPacket:r2]);

@ -88,10 +88,11 @@ bool pm(HandshakePacket* p1, HandshakePacket* p2) {
[socket startWithHandler:[PacketHandler packetHandler:^(id packet) { test(false); } [socket startWithHandler:[PacketHandler packetHandler:^(id packet) { test(false); }
withErrorHandler:^(id error, id relatedInfo, bool causedTermination) { test(!causedTermination); }] withErrorHandler:^(id error, id relatedInfo, bool causedTermination) { test(!causedTermination); }]
untilCancelled:[cc1 untilCancelledToken]]; untilCancelled:[cc1 untilCancelledToken]];
[socket secureAndSendRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:1 andPayload:[NSData data]]]; [socket secureAndSendRtpPacket:[RtpPacket rtpPacketWithDefaultsAndSequenceNumber:1
andTimeStamp:320
andPayload:[NSData data]]];
} }
testChurnUntil(!f1.isIncomplete, 5.0); testChurnUntil(!f1.isIncomplete, 5.0);
test(f1.hasResult); test(f1.hasResult);

@ -75,6 +75,17 @@
test (!same); test (!same);
} }
-(void) testGenerateSecureRandomUInt32_varies {
NSMutableSet* s = [NSMutableSet new];
for (uint i = 0; i < 10; i++) {
[s addObject:@([CryptoTools generateSecureRandomUInt32])];
}
// Note: expected false negative rate is approximately once per hundred million runs
test(s.count == 10);
}
-(void) testKnownAesCipherFeedback { -(void) testKnownAesCipherFeedback {
NSData* iv = [@"000102030405060708090a0b0c0d0e0f" decodedAsHexString]; NSData* iv = [@"000102030405060708090a0b0c0d0e0f" decodedAsHexString];
NSData* plain =[@"6bc1bee22e409f96e93d7e117393172a" decodedAsHexString]; NSData* plain =[@"6bc1bee22e409f96e93d7e117393172a" decodedAsHexString];

Loading…
Cancel
Save