1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
// SDLSmartDeviceLinkV1ProtocolHeader.m
//
#import "SDLV1ProtocolHeader.h"
const int V1PROTOCOL_HEADERSIZE = 8;
@implementation SDLV1ProtocolHeader
- (instancetype)init {
if (self = [super init]) {
_version = 1;
_size = V1PROTOCOL_HEADERSIZE;
}
return self;
}
- (NSData *)data {
// Assembles the properties in the binary header format
Byte headerBytes[V1PROTOCOL_HEADERSIZE] = {0};
Byte version = (self.version & 0xF) << 4; // first 4 bits
Byte compressed = (self.encrypted ? 1 : 0) << 3; // next 1 bit
Byte frameType = (self.frameType & 0x7); // last 3 bits
headerBytes[0] = version | compressed | frameType;
headerBytes[1] = self.serviceType;
headerBytes[2] = self.frameData;
headerBytes[3] = self.sessionID;
// Need to write the larger ints as big-endian.
UInt32 *p = (UInt32 *)&headerBytes[4];
*p = CFSwapInt32HostToBig(self.bytesInPayload); // swap the byte order
// Now put it all in an NSData object.
NSData *dataOut = [NSData dataWithBytes:headerBytes length:V1PROTOCOL_HEADERSIZE];
return dataOut;
}
- (id)copyWithZone:(NSZone *)zone {
SDLV1ProtocolHeader *newHeader = [[SDLV1ProtocolHeader allocWithZone:zone] init];
newHeader.encrypted = self.encrypted;
newHeader.frameType = self.frameType;
newHeader.serviceType = self.serviceType;
newHeader.frameData = self.frameData;
newHeader.bytesInPayload = self.bytesInPayload;
newHeader.sessionID = self.sessionID;
return newHeader;
}
- (void)parse:(NSData *)data {
NSParameterAssert(data != nil);
NSAssert(data.length >= _size, @"Error: insufficient data available to parse V1 header.");
Byte *bytePointer = (Byte *)data.bytes;
Byte firstByte = bytePointer[0];
self.encrypted = ((firstByte & 8) != 0);
self.frameType = (firstByte & 7);
self.serviceType = bytePointer[1];
self.frameData = bytePointer[2];
self.sessionID = bytePointer[3];
UInt32 *uintPointer = (UInt32 *)data.bytes;
self.bytesInPayload = CFSwapInt32BigToHost(uintPointer[1]); // Data is coming in in big-endian, so swap it.
}
- (NSString *)description {
NSMutableString *description = [[NSMutableString alloc] init];
[description appendFormat:@"Version:%i, compressed:%i, frameType:%i, serviceType:%i, frameData:%i, sessionID:%i, dataSize:%i",
self.version,
self.encrypted,
self.frameType,
self.serviceType,
self.frameData,
self.sessionID,
(unsigned int)self.bytesInPayload];
return description;
}
@end
|