Ned Ned - 2 months ago 11
Objective-C Question

Objective C objects behaving strangely (using old references)

I'm getting so very strange behavior in my Objective C library (for iPhone). What I'm trying to do is take packets coming in (off of the accessory port), append them into a NSMutableData instance variable, and then check that to see if I have any complete packets. If I do, the [containsPacket] method will return the length of the packet, otherwise it will return -1. If it contains a packet, I make a new RASPPacket object with that data, and update my receivedData object with the rest of the data (subtracting the data I just created the RASPPacket with). I loop through this until length<0 (meaning there are no more complete packets in receivedData).

When I feed it one complete packet, it works as it should (containsPacket returns the right length, and receivedData becomes an empty NSMutableData). The weird thing is that the second time I call containsPacket, it still returns the same number (13), even though receivedData is empty. I put some NSLogs in there to see what was going on (since I am disconnected from the computer I can't step through using the debugger), the output of which is below.

- (void)receive:(NSData *)packet {

[receivedData appendData:packet];

NSMutableString *dataString = [[NSMutableString alloc] init];
unsigned char *ptr = (unsigned char *)[receivedData bytes];

for(int i = 0; i < [receivedData length]; i++) {

[dataString appendFormat:@"%02X ", ptr[i]];
}

NSLog(@"Received data: %@", dataString);

int length = [RASPPacket containsPacket:receivedData];
NSLog(@"length is %i", length);

while(length > 0) {

RASPPacket *receivedPacket = [[RASPPacket alloc] initWithIncomingPacket:[NSData dataWithBytes:[receivedData bytes] length:length]];

[receivedData setData:[NSMutableData dataWithBytes:([receivedData bytes]+length) length:([receivedData length] - length)]];

dataString = [[NSMutableString alloc] init];
ptr = (unsigned char *)[receivedData bytes];

for(int i = 0; i < [receivedData length]; i++) {

[dataString appendFormat:@"%02X ", ptr[i]];
}

NSLog(@"new received data: %@", dataString);

if([receivedPacket isValidPacket]) {

[raspObject receive:receivedPacket];
NSLog(@"Complete packet is valid");
}

[receivedPacket release];

length = [RASPPacket containsPacket:receivedData];
NSLog(@"length is %i", length);
}
}


And the containsPacket method:

+ (int)containsPacket:(NSData *)thePacket {

//Return -1 by default (if it doesn't contain a complete packet)
int returnValue = -1;

unsigned char *data = (unsigned char *)[thePacket bytes];

NSMutableString *dataString = [[NSMutableString alloc] init];
unsigned char *ptr = (unsigned char *)[thePacket bytes];

for(int i = 0; i < [thePacket length]; i++) {

[dataString appendFormat:@"%02X ", ptr[i]];
}

NSLog(@"containsPacket data: %@, len %i", dataString, [thePacket length]);

NSLog(@"beginning return value %i", returnValue);

//DLE counts the number of consecutive DLE bytes (0x10). An odd number means
//we found the DLE we want, an even means it's just in a sequence in the message data
int dleCount = 0;
NSLog(@"a return value %i", returnValue);

//Start i at 2 to skip 0x10 0x01
for(int i = 2; (i < ([thePacket length] - 1)) && returnValue < 0; i++) {

NSLog(@"b return value %i, i: %i, len: %i", returnValue, i, [thePacket length] - 1);
//Check if we found 0x10 and 0x03 and there are at least three bytes extra (0x03 and checksum)
if(data[i] == 0x10 && data[i+1] == 0x03 && [thePacket length] - 3 > i) {

int j = i - 1;
dleCount = 1;

while(data[j] == 0x10 && j >= 0) {
dleCount++;
j--;
}

if(dleCount % 2) {

//Add 1 to convert to indices to length, 1 to go from 0x10 to 0x03, and 2 for checksum
returnValue = i + 2 + 1 + 1;
NSLog(@"c return value %i", returnValue);
}
}
}

NSLog(@"ending return value %i", returnValue);
return returnValue;
}


And finally, the NSLog output:

TestRaspLayer[922:6c03] Received data: 10 01 00 01 01 10 02 00 00 10 03 A1 07

TestRaspLayer[922:6c03] containsPacket data: 10 01 00 01 01 10 02 00 00 10 03 A1 07 , len 13

TestRaspLayer[922:6c03] beginning return value -1

TestRaspLayer[922:6c03] a return value -1

TestRaspLayer[922:6c03] b return value -1, i: 2, len: 12

TestRaspLayer[922:6c03] b return value -1, i: 3, len: 12

TestRaspLayer[922:6c03] b return value -1, i: 4, len: 12

TestRaspLayer[922:6c03] b return value -1, i: 5, len: 12

TestRaspLayer[922:6c03] b return value -1, i: 6, len: 12

TestRaspLayer[922:6c03] b return value -1, i: 7, len: 12

TestRaspLayer[922:6c03] b return value -1, i: 8, len: 12

TestRaspLayer[922:6c03] b return value -1, i: 9, len: 12

TestRaspLayer[922:6c03] c return value 13

TestRaspLayer[922:6c03] ending return value 13

TestRaspLayer[922:6c03] length is 13

TestRaspLayer[922:6c03] new received data:

TestRaspLayer[922:6c03] RASP receive, interface: 1, command 1, looking for interface: 9, command 1

TestRaspLayer[922:6c03] Complete packet is valid

TestRaspLayer[922:6c03] containsPacket data: , len 0

TestRaspLayer[922:6c03] beginning return value -1

TestRaspLayer[922:6c03] a return value -1

TestRaspLayer[922:6c03] b return value -1, i: 2, len: -1

TestRaspLayer[922:6c03] b return value -1, i: 3, len: -1

TestRaspLayer[922:6c03] b return value -1, i: 4, len: -1

TestRaspLayer[922:6c03] b return value -1, i: 5, len: -1

TestRaspLayer[922:6c03] b return value -1, i: 6, len: -1

TestRaspLayer[922:6c03] b return value -1, i: 7, len: -1

TestRaspLayer[922:6c03] b return value -1, i: 8, len: -1

TestRaspLayer[922:6c03] b return value -1, i: 9, len: -1

TestRaspLayer[922:6c03] c return value 13

TestRaspLayer[922:6c03] ending return value 13

TestRaspLayer[922:6c03] length is 13


The first time it is going through the valid data, the second time it isn't, and shouldn't be continuing through the for loop (since i>[thePacket length]-1).

Answer
for(int i=2; (i<([thePacket length]-1)) && returnValue<0; i++)

[thePacket length]-1 will be a very huge number (for the empty packet) since length is unsigned int.

Comments