summaryrefslogtreecommitdiff
path: root/SmartDeviceLink/SDLLifecycleSyncPDataHandler.m
blob: 58ef2769604962021296010bfa4355594ed3b9a1 (plain)
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