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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
//
// SDLLifecycleSyncPDataHandler.m
// SmartDeviceLink
//
// Created by Joel Fischer on 6/8/20.
// Copyright © 2020 smartdevicelink. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SDLLifecycleSyncPDataHandler.h"
#import "SDLConnectionManagerType.h"
#import "SDLEncodedSyncPData.h"
#import "SDLLogMacros.h"
#import "SDLOnEncodedSyncPData.h"
#import "SDLRPCNotificationNotification.h"
#import "SDLRPCParameterNames.h"
static const float DefaultConnectionTimeout = 45.0;
NS_ASSUME_NONNULL_BEGIN
@interface SDLLifecycleSyncPDataHandler ()
@property (weak, nonatomic) id<SDLConnectionManagerType> manager;
@property (strong, nonatomic) NSURLSession *urlSession;
@end
@implementation SDLLifecycleSyncPDataHandler
- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)manager {
self = [super init];
if (!self) { return nil; }
SDLLogV(@"Initializing SyncPData handler");
_manager = manager;
NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.timeoutIntervalForRequest = DefaultConnectionTimeout;
configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
_urlSession = [NSURLSession sessionWithConfiguration:configuration];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_encodedSyncPDataReceived:) name:SDLDidReceiveEncodedDataNotification object:nil];
#pragma clang diagnostic pop
return self;
}
- (void)stop {
SDLLogV(@"Stopping SyncPData handler and stopping all URL session tasks");
[self.urlSession getTasksWithCompletionHandler:^(NSArray<NSURLSessionDataTask *> * _Nonnull dataTasks, NSArray<NSURLSessionUploadTask *> * _Nonnull uploadTasks, NSArray<NSURLSessionDownloadTask *> * _Nonnull downloadTasks) {
for (NSURLSessionTask *task in dataTasks) {
[task cancel];
}
for (NSURLSessionTask *task in uploadTasks) {
[task cancel];
}
for (NSURLSessionTask *task in downloadTasks) {
[task cancel];
}
}];
}
#pragma mark - Utilities
- (void)sdl_sendEncodedSyncPData:(NSDictionary<NSString *, id> *)encodedSyncPData toURL:(NSString *)urlString withTimeout:(NSNumber *)timeout {
// Configure HTTP URL & Request
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
request.timeoutInterval = 60;
// Prepare the data in the required format
NSString *encodedSyncPDataString = [[NSString stringWithFormat:@"%@", encodedSyncPData] componentsSeparatedByString:@"\""][1];
NSArray<NSString *> *array = [NSArray arrayWithObject:encodedSyncPDataString];
NSDictionary<NSString *, id> *dictionary = @{ @"data": array };
NSError *JSONSerializationError = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:kNilOptions error:&JSONSerializationError];
if (JSONSerializationError) {
SDLLogW(@"Error attempting to create SyncPData for HTTP request: %@", JSONSerializationError);
return;
}
// Send the HTTP Request
__weak typeof(self) weakSelf = self;
[[self.urlSession uploadTaskWithRequest:request
fromData:data
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
[weakSelf sdl_syncPDataNetworkRequestCompleteWithData:data response:response error:error];
}] resume];
SDLLogV(@"OnEncodedSyncPData (HTTP Request)");
}
// Handle the OnEncodedSyncPData HTTP Response
- (void)sdl_syncPDataNetworkRequestCompleteWithData:(NSData *)data response:(NSURLResponse *)response error:(NSError *)error {
// Sample of response: {"data":["SDLKGLSDKFJLKSjdslkfjslkJLKDSGLKSDJFLKSDJF"]}
SDLLogV(@"OnEncodedSyncPData (HTTP Response): %@", response);
// Validate response data.
if (data == nil || data.length == 0) {
SDLLogW(@"OnEncodedSyncPData (HTTP Response): no data returned");
return;
}
// Convert data to RPCRequest
NSError *JSONConversionError = nil;
NSDictionary<NSString *, id> *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&JSONConversionError];
if (JSONConversionError) {
SDLLogE(@"Error converting EncodedSyncPData response dictionary: %@", JSONConversionError);
return;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
SDLEncodedSyncPData *request = [[SDLEncodedSyncPData alloc] init];
#pragma clang diagnostic pop
request.data = responseDictionary[@"data"];
[self.manager sendConnectionManagerRequest:request withResponseHandler:nil];
}
#pragma mark - Notifications
- (void)sdl_encodedSyncPDataReceived:(SDLRPCNotificationNotification *)notification {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
SDLOnEncodedSyncPData *message = notification.notification;
#pragma clang diagnostic pop
// If URL != nil, perform HTTP Post and don't pass the notification to proxy listeners
SDLLogV(@"OnEncodedSyncPData: %@", message);
NSString *urlString = (NSString *)message.parameters[SDLRPCParameterNameURLUppercase];
NSDictionary<NSString *, id> *encodedSyncPData = (NSDictionary<NSString *, id> *)message.parameters[SDLRPCParameterNameData];
NSNumber *encodedSyncPTimeout = (NSNumber *)message.parameters[SDLRPCParameterNameTimeoutCapitalized];
if (urlString && encodedSyncPData && encodedSyncPTimeout) {
[self sdl_sendEncodedSyncPData:encodedSyncPData toURL:urlString withTimeout:encodedSyncPTimeout];
}
}
@end
NS_ASSUME_NONNULL_END
|