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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
// SDLRPCPayload.h
//
#import "SDLRPCPayload.h"
#import "SDLDebugTool.h"
const NSUInteger RPC_HEADER_SIZE = 12;
@implementation SDLRPCPayload
- (instancetype)initWithData:(NSData *)data {
unsigned long dataLength = data.length;
if (data == nil || dataLength == 0) {
[SDLDebugTool logInfo:@"Error: data is nil."];
return nil;
}
if (dataLength < RPC_HEADER_SIZE) {
[SDLDebugTool logInfo:@"Error: insfficient data to form RPC header."];
return nil;
}
if (self = [self init]) {
@try {
// Setup our pointers for data access
UInt8 *bytePointer = (UInt8 *)data.bytes;
UInt32 *ui32Pointer = (UInt32 *)data.bytes;
// Extract the parts
UInt8 rpcType = (bytePointer[0] & 0xF0) >> 4;
self.rpcType = rpcType;
UInt32 functionID = ui32Pointer[0];
functionID = CFSwapInt32BigToHost(functionID) & 0x0FFFFFFF;
self.functionID = functionID;
UInt32 correlationID = ui32Pointer[1];
correlationID = CFSwapInt32BigToHost(correlationID);
self.correlationID = correlationID;
UInt32 jsonDataSize = ui32Pointer[2];
jsonDataSize = CFSwapInt32BigToHost(jsonDataSize);
NSData *jsonData = nil;
NSUInteger offsetOfJSONData = RPC_HEADER_SIZE;
if (jsonDataSize > 0 && jsonDataSize <= dataLength - RPC_HEADER_SIZE) {
jsonData = [data subdataWithRange:NSMakeRange(offsetOfJSONData, jsonDataSize)];
}
self.jsonData = jsonData;
NSData *binaryData = nil;
NSUInteger offsetOfBinaryData = RPC_HEADER_SIZE + jsonDataSize;
NSInteger binaryDataSize = data.length - jsonDataSize - RPC_HEADER_SIZE;
if (binaryDataSize > 0) {
binaryData = [data subdataWithRange:NSMakeRange(offsetOfBinaryData, binaryDataSize)];
}
self.binaryData = binaryData;
} @catch (NSException *e) {
// Print exception information
[SDLDebugTool logFormat:@"NSException caught in SDLRPCPayload::initWithData\nName: %@\nReason: %@\nData: %@", e.name, e.reason, data.debugDescription];
return nil;
}
}
return self;
}
- (NSData *)data {
// Header is:
// RPC Type - first 4 bits
// RPC Function ID - next 28 bits
// Correlation ID - next 32 bits
// JSON size - next 32 bits
UInt8 headerBuffer[RPC_HEADER_SIZE];
*(UInt32 *)&headerBuffer[0] = CFSwapInt32HostToBig(self.functionID);
*(UInt32 *)&headerBuffer[4] = CFSwapInt32HostToBig(self.correlationID);
*(UInt32 *)&headerBuffer[8] = CFSwapInt32HostToBig((UInt32)self.jsonData.length);
UInt8 rpcType = (self.rpcType & 0x0F) << 4;
headerBuffer[0] &= 0x0F;
headerBuffer[0] |= rpcType;
// Serialize the header, the json data then the binary data
NSMutableData *dataOut = [NSMutableData dataWithCapacity:[self size]];
[dataOut appendBytes:&headerBuffer length:12];
[dataOut appendData:self.jsonData];
[dataOut appendData:self.binaryData];
return dataOut;
}
- (NSUInteger)size {
NSUInteger headerSize = RPC_HEADER_SIZE;
NSUInteger jsonDataSize = self.jsonData.length;
NSUInteger binaryDataSize = self.binaryData.length;
return (headerSize + jsonDataSize + binaryDataSize);
}
- (NSString *)description {
NSMutableString *description = [[NSMutableString alloc] init];
[description appendFormat:@" rpcType:%i, functionID:%i, correlationID:%i, json:%lu bytes, binary:%lu bytes", self.rpcType, (unsigned int)self.functionID, (unsigned int)self.correlationID, (unsigned long)self.jsonData.length, (unsigned long)self.binaryData.length];
return description;
}
+ (id)rpcPayloadWithData:(NSData *)data {
return [[SDLRPCPayload alloc] initWithData:data];
}
@end
|